]> git.sesse.net Git - mlt/blobdiff - src/modules/linsys/consumer_SDIstream.c
Fix compile error on Windows.
[mlt] / src / modules / linsys / consumer_SDIstream.c
index 132446c1cde7baca6814bf6ebcccc91514a006a6..8e7cec5e8f243265cc4e3a69a778ff91e12991ce 100644 (file)
  * System No.  System nomenclature             Form of scanning        Frame rate                              Embedded Audio                  MLT profile             Linsys board support (model)
  * SD PAL              720 × 576/50/I                 interlaced                      25 HZ                                   8 x AES (16 channels)   dv_pal                  180,145,159,107
  * SD PAL              720 × 576/50/I                 interlaced                      25 HZ                                   4 x AES (8 channels)    dv_pal                  193
- * SD NTSC             720 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   8 x AES (16 channels)   sdi_486i_5994   TODO:180,145,159,107
- * SD NTSC             720 × 480/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
+ * SD NTSC             720 × 486/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   8 x AES (16 channels)   sdi_486i_5994   TODO:180,145,159,107
+ * SD NTSC             720 × 486/59.94/I              interlaced                      30000/1001 ~ 29.97 HZ   4 x AES (8 channels)    sdi_486i_5994   193
  *
  **/
 
 #include <framework/mlt_frame.h>
 #include <framework/mlt_profile.h>
 #include <framework/mlt_log.h>
+#include <framework/mlt_events.h>
 #include <stdlib.h>
 #include <string.h>
 #include <pthread.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #ifdef WITH_JPEG
 // for JPEG output
@@ -156,7 +159,8 @@ struct consumer_SDIstream_s {
        int height;
 
        struct audio_format audio_format;
-       /** device file:
+       /**
+        * device file:
         *              /dev/sditx0
         *              /dev/sdivideotx0
         *              /dev/sdiaudiotx0
@@ -164,20 +168,21 @@ struct consumer_SDIstream_s {
        char *device_file_video; // Path for SDI output
        char *device_file_audio; // Path for exlusive SDI audio output
 
-       /* write own HANC (ancillary data) is available for:
+       /**
+        *  write own HANC (ancillary data) is available for:
         * SDI board ASSY 193 HD        'blanking=false'
         * SDI board ASSY 180 SD quad   'blanking=true'
         * SDI board ASSY 145 SD single 'blanking=true'
         *
         * 0=false, 1=true
         *
-        * */
+        **/
        uint8_t blanking;
 
        // our audio channel pair for this frame
        int16_t audio_buffer[MAX_AUDIO_STREAMS][MAX_AUDIO_SAMPLES]; // The SDI audio channel pairs for this frame
 
-       char *video_fmt_name; // 1080i25, 1080p25, 576i50, 480i2997, ...
+       char *video_fmt_name; // 1080i25, 1080p25, 576i50, 486i2997, ...
 
 };
 
@@ -191,7 +196,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 **************************************
@@ -206,7 +211,7 @@ int convertYCBCRtoRGB(int y1, int cb, int cr, int y2, int * target_rgb);
 mlt_consumer consumer_SDIstream_init(mlt_profile profile, mlt_service_type type, const char *id, char *arg) {
 
        // Create the consumer object
-       consumer_SDIstream this = calloc(sizeof(struct consumer_SDIstream_s), 1);
+       consumer_SDIstream this = calloc( 1, sizeof(struct consumer_SDIstream_s) );
 
        // If malloc and consumer init ok
        if (this != NULL && mlt_consumer_init(&this->parent, this, profile) == 0) {
@@ -229,13 +234,15 @@ 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++) {
                                this->audio_buffer[i][j] = j;
                        }
                }
+               
+               mlt_events_register( MLT_CONSUMER_PROPERTIES(parent), "consumer-fatal-error", NULL );
 
                // Return the consumer produced
                return parent;
@@ -337,21 +344,6 @@ static void *consumer_thread(void *arg) {
 
        int counter = 0; // each second we save a Jpeg
 
-       // set blanking flag; is not nessary we write no own blanking(HANC) for HD board ASSY 193
-       if (mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking") != NULL) {
-               // set value
-               if (strcmp(strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking")), "false")) {
-                       this->blanking = 1;
-               } else if (strcmp(strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking")), "true")) {
-                       this->blanking = 0;
-               } else {
-                       this->blanking = 1;
-               }
-       } else {
-               // set default value without HD board, also with blanking
-               this->blanking = 1;
-       }
-
        // set properties (path) for device files
        if (mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "dev_video") != NULL) {
                this->device_file_video = strdup(mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "dev_video"));
@@ -365,13 +357,54 @@ static void *consumer_thread(void *arg) {
                }
        }
 
-       // Define a frame pointer
-       mlt_frame frame;
+       // Set additional device file defaults
+       struct stat st;
+       int fd = -1;
+       if (this->device_file_video)
+               fd = stat(this->device_file_video, &st);
+       if (fd == -1) {
+               if (this->device_file_video)
+                       free(this->device_file_video);
+               this->device_file_video = strdup("/dev/sdivideotx0");
+       } else {
+               close(fd);
+       }
+       if (this->device_file_audio) {
+               fd = stat(this->device_file_audio, &st);
+               if (fd == -1) {
+                       if (this->device_file_audio)
+                               free(this->device_file_audio);
+                       this->device_file_audio = strdup("/dev/sdiaudiotx0");
+               } else {
+                       close(fd);
+               }
+       } else if (this->device_file_video &&
+                       strstr(this->device_file_video, "sdivideotx")) {
+               if (this->device_file_audio)
+                       free(this->device_file_audio);
+               this->device_file_audio = strdup("/dev/sdiaudiotx0");
+       }
 
-       if (!sdi_init(this->device_file_video, this->device_file_audio, this->blanking, mlt_service_profile((mlt_service) consumer))) {
-               exit(0);
+       // set blanking flag; is not nessary we write no own blanking(HANC) for HD board ASSY 193
+       if (mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking")) {
+               // set value
+               if (!strcmp( mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking"), "false")) {
+                       this->blanking = 0;
+               } else if (!strcmp( mlt_properties_get(MLT_CONSUMER_PROPERTIES( consumer ), "blanking"), "true")) {
+                       this->blanking = 1;
+               } else {
+                       this->blanking = mlt_properties_get_int(MLT_CONSUMER_PROPERTIES( consumer ), "blanking");
+               }
+       } else if (this->device_file_video && strstr(this->device_file_video, "sdivideotx")) {
+               this->blanking = 0;
+       } else {
+               // set default value without HD board, also with blanking
+               this->blanking = 1;
        }
 
+       // Define a frame pointer
+       mlt_frame frame;
+
        // set Datablock number for SDI encoding
        int my_dbn = 1;
 
@@ -379,14 +412,22 @@ static void *consumer_thread(void *arg) {
        unsigned int count = 0;
 
        // Tell the framework how we want our audio and video
-       int frequency = 48000;
-       int channels = 0;
-       int samples = mlt_sample_calculator(fps, frequency, count++);
-
-       this->audio_format.aformat = mlt_audio_s16;
-       this->audio_format.channels = 0;
+       int frequency = this->audio_format.sample_rate;
+       int channels = mlt_properties_get_int(  MLT_CONSUMER_PROPERTIES(consumer), "channels" );
+       int samples;
+
+       // set number of audio channels, linsys vidport model 193 is limited to 8 channels (4AES frames)
+       this->audio_format.channels = 8; /* 0,2,4,6,8 */
+       this->audio_format.aformat = mlt_audio_s16; /* 16, 24, 32 */
+       this->audio_format.sample_rate = 48000;
        this->pix_fmt = mlt_image_yuv422;
 
+       if (this->device_file_video && this->device_file_audio &&
+               !sdi_init(this->device_file_video, this->device_file_audio, this->blanking, mlt_service_profile((mlt_service) consumer), &this->audio_format)) {
+               mlt_log_fatal( MLT_CONSUMER_SERVICE(consumer), "failed to initialize\n" );
+               mlt_events_fire( MLT_CONSUMER_PROPERTIES(consumer), "consumer-fatal-error", NULL );
+       }
+
        uint8_t *video_buffer;
        int16_t *audio_buffer_tmp; // the upstream audio buffer
 
@@ -412,15 +453,16 @@ static void *consumer_thread(void *arg) {
                                mlt_frame_get_image(frame, &video_buffer, &this->pix_fmt, &this->width, &this->height, 1);
 
                                // Get the audio from this frame and save it to our audio_buffer
+                               samples = mlt_sample_calculator(fps, frequency, count++);
                                mlt_frame_get_audio(frame, (void**) &audio_buffer_tmp, &this->audio_format.aformat, &frequency, &channels, &samples);
 
                                this->audio_format.sample_rate = frequency;
                                this->audio_format.samples = samples;
 
-                               // TODO, current hard coded to all 8 channels, also we write 8 channels to the sdi board
-                               // the Linys SDI board must be right configured with the same number of channels!!!
-                               this->audio_format.channels = 8;
-                               // this->audio_format.channels = channels; // take given number of channels
+                               /* TODO: Audio is currently hard coded to 8 channels because write 8 channels to the sdi board.
+                                The Linys SDI board has to be configured with the same number of channels!
+                                this->audio_format.channels = channels; // take given number of channels
+                                */
 
                                /* Tell the sdi_generator.c to playout our frame
                                 * 8 AES (8 x stereo channels are possible, max. 16 channels) Linsys SD board model:    107, 159, 145, 180
@@ -466,6 +508,7 @@ static void *consumer_thread(void *arg) {
                                        } else if (save_jpegs > 0) {
                                                counter++;
                                        }
+                                       mlt_events_fire(MLT_CONSUMER_PROPERTIES( consumer ), "consumer-frame-show", frame, NULL );
                                } else {
                                        mlt_log_warning(MLT_CONSUMER_SERVICE(consumer), "Videobuffer was NULL, skipping playout!\n");
                                }
@@ -579,69 +622,42 @@ 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;