]> git.sesse.net Git - mlt/commitdiff
Improve performance of sdi consumer (patch from BCE).
authorDan Dennedy <dan@dennedy.org>
Thu, 11 Mar 2010 05:24:01 +0000 (21:24 -0800)
committerDan Dennedy <dan@dennedy.org>
Thu, 11 Mar 2010 05:24:01 +0000 (21:24 -0800)
consumer_SDIstream.c
- convertYCBCRtoRGB: different calculation

sdi_generator.h
- SDIAUDIO transmitter event definitions

sdi_generator.c
- pack changed to pack8 instead of packv210
- Transmitter events are checked only once a frame
- create_HD_SDI_Line and create_SD_SDI_Line do not calculate the current
position in the video_buffer for each sample. Now it is done once a
line.

src/modules/linsys/consumer_SDIstream.c
src/modules/linsys/sdi_generator.c
src/modules/linsys/sdi_generator.h

index 132446c1cde7baca6814bf6ebcccc91514a006a6..de3923ada22fe60e9bb84318e7103196fe1cf757 100644 (file)
@@ -191,7 +191,7 @@ static void consumer_close(mlt_consumer parent);
 static void *consumer_thread(void *);
 
 static void consumer_write_JPEG(char * path, uint8_t **vBuffer, mlt_profile myProfile);
-int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, int * target_rgb);
+int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, uint8_t * target_rgb);
 
 /*****************************************************************************************************
  ****************************************** SDI Master Consumer **************************************
@@ -229,7 +229,7 @@ mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type,
                parent->stop = consumer_stop;
                parent->is_stopped = consumer_is_stopped;
 
-               // Set explizit to zero or other value
+               // Set explicit to zero or other value
                int i, j;
                for (i = 0; i < MAX_AUDIO_STREAMS; i++) {
                        for (j = 0; j < MAX_AUDIO_SAMPLES; j++) {
@@ -579,69 +579,44 @@ static void consumer_write_JPEG(char * filename, uint8_t **vBuffer, mlt_profile
  * @param target pointer
  * @return 0 upon success
  **/
-int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, int * target_rgb) {
+int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, uint8_t * target_rgb) {
 
 #ifdef WITH_JPEG
 
-       uint32_t tmp = 0;
+       if(y1 > 235)
+               y1 = 235;
+       if(y1 < 16)
+               y1 = 16;
+
+       if(y2 > 235)
+               y2 = 235;
+       if(y2 < 16)
+               y2 = 16;
+
+       if(cr > 240)
+               cr = 240;
+       if(cr < 16)
+               cr = 16;
+
+       if(cb > 240)
+               cb = 240;
+       if(cb < 16)
+               cb = 16;
+
        uint8_t r1, g1, b1, r2, g2, b2;
 
        //pointer to current output buffer position
        uint8_t * target_pointer = target_rgb;
 
-       // colorconversion for first pixel and output to rgb buffer
-       /* B1 */
-       tmp = 1.164 * (y1 - 16) + 2.017 * (cb - 128);
-       if (tmp > 255)
-               tmp = 255;
-       if (tmp < 0)
-               tmp = 0;
-       b1 = tmp;
-
-       /* G1 */
-       tmp = 1.164 * (y1 - 16) - 0.813 * (cr - 128) - 0.392 * (cb - 128);
-       if (tmp > 255)
-               tmp = 255;
-       if (tmp < 0)
-               tmp = 0;
-       g1 = tmp;
-
-       /* R1 */
-       tmp = 1.164 * (y1 - 16) + 1.596 * (cr - 128);
-       if (tmp > 255)
-               tmp = 255;
-       if (tmp < 0)
-               tmp = 0;
-       r1 = tmp;
-
-       // colorconversion for second pixel and output to rgb buffer
-       /* B2 */
-       tmp = 1.164 * (y2 - 16) + 2.017 * (cb - 128);
-       if (tmp > 255)
-               tmp = 255;
-       if (tmp < 0)
-               tmp = 0;
-       b2 = tmp;
-
-       /* G2 */
-       tmp = 1.164 * (y2 - 16) - 0.813 * (cr - 128) - 0.392 * (cb - 128);
-       if (tmp > 255)
-               tmp = 255;
-       if (tmp < 0)
-               tmp = 0;
-       g2 = tmp;
-
-       /* R2 */
-       tmp = 1.164 * (y2 - 16) + 1.596 * (cr - 128);
-       if (tmp > 255)
-               tmp = 255;
-       if (tmp < 0)
-               tmp = 0;
-       r2 = tmp;
-
-       //      r=y+1.5958*v;
-       //  g=y-0.39173*u-0.81290*v;
-       //  b=y+2.017*u;
+       r1 = y1 + 1.402 * (cr - 128);
+       g1 = y1 - 0.34414 * (cb - 128) - 0.71414 * (cr - 128);
+       b1 = y1 + 1.772 * (cb - 128);
+
+
+       r2 = y2 + 1.402 * (cr - 128);
+       g2 = y2 - 0.34414 * (cb - 128) - 0.71414 *(cr - 128);
+       b2 = y2 + 1.772 * (cb - 128);
+
 
        *target_pointer++ = r1;
        *target_pointer++ = g1;
index 0004f741e6c0e59583425cfe48ab988a8b25d3f8..6416ad31379f1f202fd41319aa7fa7070d806909 100644 (file)
@@ -141,9 +141,9 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
        info.blanking = blanking;
 
        // set pack methode for SDI word conversion
-       //pack = pack8;
+       pack = pack8;
        //pack = pack10;
-       pack = pack_v210;
+       //pack = pack_v210;
 
        // check format
        if (myProfile->width == 1920 && myProfile->height == 1080 && myProfile->frame_rate_num == 30 && myProfile->frame_rate_den == 1 && myProfile->progressive
@@ -201,16 +201,16 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
                        && myProfile->progressive == 0) {
                info.fmt = &FMT_480i5994;
        } else {
-               printf("Consumer gets unknown format: %s", myProfile->description);
+               printf("Consumer got unknown format: %s", myProfile->description);
                info.fmt = &FMT_576i50;
        }
 
        printf("Consumer use format: %s\nProfile: %i %i %i %i %i\n", myProfile->description, myProfile->width, myProfile->height, myProfile->frame_rate_num,
                        myProfile->frame_rate_den, myProfile->progressive);
 
-       // Check if the format support own blanking (note: model 193 support currently only active video at the video device file)
+       // Check if the format supports own blanking (note: model 193 supports currently only active video at the video device file)
        if (info.blanking && info.fmt != &FMT_576i50) {
-               printf("SDI consumer doesn't support blanking(HANC) for this configurred SD board and SDI format. Try arguemnt: blanking=false\n");
+               printf("SDI consumer doesn't support blanking(HANC) for the configured SD board and SDI format. Try argument: blanking=false\n");
                return EXIT_FAILURE;
        }
 
@@ -223,12 +223,12 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
                printf("SDI consumer use video device file: %s\n", device_file_video);
        }
 
-       // Check if seperat device file for audio must use
+       // Check if we have to use a separate device file for audio
        if (device_file_audio != NULL) {
                // open file handler for audio output
                if ((fh_sdi_audio = open(device_file_audio, O_WRONLY | O_CREAT, 0777)) == -1) {
                        perror(NULL);
-                       printf("\ncould not open audio output destination: %s\n", device_file_audio);
+                       printf("\nCould not open audio output destination: %s\n", device_file_audio);
                        return EXIT_FAILURE;
                }
                printf("SDI consumer use audio device file: %s\n", device_file_audio);
@@ -248,7 +248,7 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
                        AESChannelStatusBitArray[i] = 0;
 
                /**
-                * Professionel Format - Channel Status Bits
+                * Professional Format - Channel Status Bits
                 **/
                ////// Byte 0 //////
                AESChannelStatusBitArray[0] = 1; // professional format
@@ -261,7 +261,7 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
 
                AESChannelStatusBitArray[5] = 0; // locked
 
-               AESChannelStatusBitArray[6] = 0; // sample frequncy Fs: [01]48kHz, [10]44kHz, [11]32kHz
+               AESChannelStatusBitArray[6] = 0; // sample frequency Fs: [01]48kHz, [10]44kHz, [11]32kHz
                AESChannelStatusBitArray[7] = 1; // ^
                ////// Byte 1 //////
                AESChannelStatusBitArray[8] = 0; // channel mode: [0000] not indicated, [0001]2channels, [0010]1channel mono, ...
@@ -339,7 +339,6 @@ static int sdi_init(char *device_video, char *device_audio, uint8_t blanking, ml
                }
        }
 
-       // hack/overwrite because we use default the pack_v210() not as befor the pack10()
        //(*10/8 because we store (TOTAL_SAMPLES*TOTAL_LINES) words with 10 bit in this 8 bit array) )
        if (info.fmt == &FMT_576i50 && info.blanking) {
                sdi_frame_size = info.fmt->samples_per_line * 10 / 8 * info.fmt->lines_per_frame;
@@ -777,36 +776,40 @@ static int sdi_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS][MAX_
        // Write the complete frame to output
        // The "while" is necessary because the sdi device file does not take the complete frame at once
        written_bytes = 0;
-       while (bytes < sdi_frame_size) {
+       while (bytes < sdi_frame_size)
+       {
 
                if ((written_bytes = write(fh_sdi_video, data + bytes, sdi_frame_size - bytes)) < 0) {
                        fprintf(stderr, "\nunable to write SDI video.\n");
                        return -1;
                }
                bytes += written_bytes;
+       }
 
-               // Check for events of the SDI board
-               unsigned int val;
-               if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
-                       // Maybe this is not an SDI device...
-                       fprintf(stderr, "SDI VIDEO output:");
-                       perror("unable to get the transmitter event flags");
-               } else if (val) {
-                       if (val & SDI_EVENT_TX_BUFFER) {
-                               printf("SDI VIDEO driver transmit buffer queue underrun "
-                                       "detected.\n");
-                       }
-                       if (val & SDI_EVENT_TX_FIFO) {
-                               printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
-                               // TODO react
-                       }
-                       if (val & SDI_EVENT_TX_DATA) {
-                               printf("SDI VIDEO transmit data change detected.\n");
-                       }
+       // Check for events of the SDI board
+       unsigned int val;
+       if (ioctl(fh_sdi_video, SDI_IOC_TXGETEVENTS, &val) < 0) {
+               // Maybe this is not an SDI device...
+               //fprintf(stderr, "SDI VIDEO output:");
+               //perror("unable to get the transmitter event flags");
+       } else if (val) {
+               if (val & SDI_EVENT_TX_BUFFER) {
+                       printf("SDI VIDEO driver transmit buffer queue underrun "
+                               "detected.\n");
+                       fflush(stdout);
+               }
+               if (val & SDI_EVENT_TX_FIFO) {
+                       printf("SDI VIDEO onboard transmit FIFO underrun detected.\n");
+                       fflush(stdout);
+               }
+               if (val & SDI_EVENT_TX_DATA) {
+                       printf("SDI VIDEO transmit data change detected.\n");
+                       fflush(stdout);
                }
-               fflush(stdout);
        }
 
+
+
        // if available write audio data
        if (fh_sdi_audio) {
 
@@ -900,25 +903,25 @@ static int sdi_playout(uint8_t *vBuffer, int16_t aBuffer[MAX_AUDIO_STREAMS][MAX_
 
                        sample_number++;
 
-//                     // Check for events of the SDI board (only firmware 0.9)
-//                     unsigned int val;
-//                     if (ioctl(fh_sdi_audio, SDI_IOC_TXGETEVENTS, &val) < 0) {
-//                             //Maybe this is not an SDI device...
-//                             fprintf(stderr, "SDI AUDIO output:");
-//                             perror("unable to get the transmitter event flags");
-//                     } else if (val) {
-//                             if (val & SDI_EVENT_TX_BUFFER) {
-//                                     printf("SDI AUDIO driver transmit buffer queue underrun "
-//                                             "detected.\n");
-//                             }
-//                             if (val & SDI_EVENT_TX_FIFO) {
-//                                     printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
-//                                     //TODO react
-//                             }
-//                             if (val & SDI_EVENT_TX_DATA) {
-//                                     printf("SDI AUDIO transmit data change detected.\n");
-//                             }
-//                     }
+                       // Check for events of the SDI audio device
+                       unsigned int val;
+                       if (ioctl(fh_sdi_audio, SDIAUDIO_IOC_TXGETEVENTS, &val) < 0) {
+                               //Maybe this is not an SDI device...
+                               //                              fprintf(stderr, "SDI AUDIO output:");
+                               //                              perror("unable to get the transmitter event flags");
+                       } else if (val) {
+                               if (val & SDIAUDIO_EVENT_TX_BUFFER) {
+                                       printf("SDI AUDIO driver transmit buffer queue underrun "
+                                                       "detected.\n");
+                               }
+                               if (val & SDIAUDIO_EVENT_TX_FIFO) {
+                                       printf("SDI AUDIO onboard transmit FIFO underrun detected.\n");
+                                       //TODO react
+                               }
+                               if (val & SDIAUDIO_EVENT_TX_DATA) {
+                                       printf("SDI AUDIO transmit data change detected.\n");
+                               }
+                       }
                }
        }
 
@@ -1039,6 +1042,14 @@ static inline int create_SD_SDI_Line(uint16_t *buf, const struct line_info *info
        *p++ = info->xyz->sav;
        //#########################################################################################
 
+
+       // Because we skip the first line of video, it can happen that we read too far in the buffer
+       if (active_video_line >= info->fmt->active_lines_per_frame) {
+               active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
+       }
+       //Index of the start of the current line in the video_buffer
+       int start_of_current_line  = active_video_line * info->fmt->active_samples_per_line;
+
        // If VBlank then fill the line with 0x200 and 0x040 (total black)
        switch (active) {
        default:
@@ -1055,30 +1066,25 @@ static inline int create_SD_SDI_Line(uint16_t *buf, const struct line_info *info
 
                        // shift "<< 2" because 8 bit data in 10 bit word
 
-                       // Because we skip the first line of video, it can happen that we read too far in the buffer
-                       if (active_video_line >= info->fmt->active_lines_per_frame) {
-                               active_video_line = info->fmt->active_lines_per_frame - 1; // in SD PAL was set 575
-                       }
-
-                       *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) + 1] << 2; // Cb
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cb
                        p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040; // check values
                        if (*(p - 1) > 0x3c0)
                                *(p - 1) = 0x3c0;
-                       *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y1
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y1
                        p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
                        if (*(p - 1) > 0x3ac)
                                *(p - 1) = 0x3ac;
-                       *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) + 1] << 2; // Cr
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) + 1] << 2; // Cr
                        p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
                        if (*(p - 1) > 0x3c0)
                                *(p - 1) = 0x3c0;
-                       *p = video_buffer[(active_video_line * 1440) + ((p - 288) - buf) - 1] << 2; // Y2
+                       *p = video_buffer[start_of_current_line + ((p - 288) - buf) - 1] << 2; // Y2
                        p++;
                        if (*(p - 1) < 0x040)
                                *(p - 1) = 0x040;
@@ -1105,6 +1111,14 @@ static inline int create_HD_SDI_Line(uint16_t *buf, const struct line_info *info
        uint16_t *p = buf, *endp, ln;
        uint16_t samples = info->blanking ? info->fmt->samples_per_line : info->fmt->active_samples_per_line;
 
+
+       if (active_video_line >= info->fmt->active_lines_per_frame) {
+               active_video_line = info->fmt->active_lines_per_frame - 1;
+       }
+
+       int start_of_current_line = active_video_line * info->fmt->active_samples_per_line;
+
+
        if (info->blanking) {
 
                // write line with TRS(EAV) ANC(audio) TRS(SAV) activeVideo(CbY1CrY2)
@@ -1199,42 +1213,30 @@ static inline int create_HD_SDI_Line(uint16_t *buf, const struct line_info *info
 
                while (p < (buf + samples)) {
 
-                       if (active_video_line >= info->fmt->active_lines_per_frame) {
-                               active_video_line = info->fmt->active_lines_per_frame - 1;
-                       }
-
-                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
-                       //                      *p++ = sample > 1440 ? 735 : (video_buffer[sample] << 2);
-                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
-                       //                      *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
-                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1;
-                       //                      *p++ = sample > 1440 ? 793 : (video_buffer[sample] << 2);
-                       //                      sample = (active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1;
-                       //                      *p++ = sample > 1440 ? 335 : (video_buffer[sample] << 2);
 
-                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cb
+                       *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cb
                        p++;
-                       // check values, but need manny resources
+                       //check values, this needs a lot of resources
                        //                      if (*(p - 1) < 0x040)
                        //                              *(p - 1) = 0x040;
                        //                      if (*(p - 1) > 0x3c0)
                        //                              *(p - 1) = 0x3c0;
                        //
-                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y1
+                       *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y1
                        p++;
                        //                      if (*(p - 1) < 0x040)
                        //                              *(p - 1) = 0x040;
                        //                      if (*(p - 1) > 0x3ac)
                        //                              *(p - 1) = 0x3ac;
                        //
-                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) + 1] << 2; // Cr
+                       *p = video_buffer[start_of_current_line + (p - buf) + 1] << 2; // Cr
                        p++;
                        //                      if (*(p - 1) < 0x040)
                        //                              *(p - 1) = 0x040;
                        //                      if (*(p - 1) > 0x3c0)
                        //                              *(p - 1) = 0x3c0;
                        //
-                       *p = video_buffer[(active_video_line * info->fmt->active_samples_per_line) + (p - buf) - 1] << 2; // Y2
+                       *p = video_buffer[start_of_current_line + (p - buf) - 1] << 2; // Y2
                        p++;
                        //                      if (*(p - 1) < 0x040)
                        //                              *(p - 1) = 0x040;
index 0c5ec595c100fb1b7243d5c74949f95d0ff87dad..c6ee61f8a92dd0d69d438e276f0dede99fb03d63 100644 (file)
 #define SDI_EVENT_TX_DATA_ORDER                2
 #define SDI_EVENT_TX_DATA              (1 << SDI_EVENT_TX_DATA_ORDER)
 
+
+// part of the linsys sdiaudio.h
+
+#define SDIAUDIO_IOC_TXGETCAP                  _IOR(SDIAUDIO_IOC_MAGIC, 1, unsigned int)
+#define SDIAUDIO_IOC_TXGETEVENTS               _IOR(SDIAUDIO_IOC_MAGIC, 2, unsigned int)
+#define SDIAUDIO_IOC_TXGETBUFLEVEL             _IOR(SDIAUDIO_IOC_MAGIC, 3, unsigned int)
+#define SDIAUDIO_IOC_TXGETTXD                  _IOR(SDIAUDIO_IOC_MAGIC, 4, int)
+
+#define SDIAUDIO_IOC_MAGIC '~' /* This ioctl magic number is currently free. See
+                          * /usr/src/linux/Documentation/ioctl-number.txt */
+/* Transmitter event flag bit locations */
+#define SDIAUDIO_EVENT_TX_BUFFER_ORDER 0
+#define SDIAUDIO_EVENT_TX_BUFFER       (1 << SDIAUDIO_EVENT_TX_BUFFER_ORDER)
+#define SDIAUDIO_EVENT_TX_FIFO_ORDER   1
+#define SDIAUDIO_EVENT_TX_FIFO         (1 << SDIAUDIO_EVENT_TX_FIFO_ORDER)
+#define SDIAUDIO_EVENT_TX_DATA_ORDER   2
+#define SDIAUDIO_EVENT_TX_DATA         (1 << SDIAUDIO_EVENT_TX_DATA_ORDER)
+
 // Filehandler for sdi output
 static int fh_sdi_video;
 static int fh_sdi_audio;
 
+
 #define MAX_SAMPLES_PER_LINE (2*2750)
 #define MAX_LINES_PER_FRAME 1125
 #define MAX_AUDIO_STREAMS (8)