Esempio n. 1
0
vbi_capture *
vbi_capture_bktr_new		(const char *		dev_name,
				 int			scanning,
				 unsigned int *		services,
				 int			strict,
				 char **		errstr,
				 vbi_bool		trace)
{
	char *error = NULL;
	char *driver_name = _("BKTR driver");
	vbi_capture_bktr *v;

	pthread_once (&vbi_init_once, vbi_init);

	assert(services && *services != 0);

	if (!errstr)
		errstr = &error;
	*errstr = NULL;

	printv ("Try to open bktr vbi device, "
		"libzvbi interface rev.\n  %s\n", rcsid);

	if (!(v = (vbi_capture_bktr *) calloc(1, sizeof(*v)))) {
		asprintf(errstr, _("Virtual memory exhausted."));
		errno = ENOMEM;
		goto failure;
	}

	vbi_raw_decoder_init (&v->dec);

	v->capture.parameters = bktr_parameters;
	v->capture._delete = bktr_delete;
	v->capture.get_fd = bktr_fd;

	v->fd = device_open (v->capture.sys_log_fp, dev_name, O_RDONLY, 0);
	if (-1 == v->fd) {
		asprintf(errstr, _("Cannot open '%s': %s."),
			 dev_name, strerror(errno));
		goto io_error;
	}

	printv("Opened %s\n", dev_name);

	/*
	 *  XXX
	 *  Can we somehow verify this really is /dev/vbiN (bktr) and not
	 *  /dev/hcfr (halt and catch fire on read) ?
	 */

	v->dec.bytes_per_line = 2048;
	v->dec.interlaced = FALSE;
	v->dec.synchronous = TRUE;

	v->dec.count[0]	= 16;
	v->dec.count[1] = 16;

	switch (scanning) {
	default:
		/* fall through */

	case 625:
		/* Not confirmed */
		v->dec.scanning = 625;
		v->dec.sampling_rate = 35468950;
		v->dec.offset = (int)(10.2e-6 * 35468950);
		v->dec.start[0] = 22 + 1 - v->dec.count[0];
		v->dec.start[1] = 335 + 1 - v->dec.count[1];
		break;

	case 525:
		/* Not confirmed */
		v->dec.scanning = 525;
		v->dec.sampling_rate = 28636363;
		v->dec.offset = (int)(9.2e-6 * 28636363);
		v->dec.start[0] = 10;
		v->dec.start[1] = 273;
		break;
	}

	v->time_per_frame =
		(v->dec.scanning == 625) ? 1.0 / 25 : 1001.0 / 30000;

	v->select = FALSE; /* XXX ? */

	printv("Guessed videostandard %d\n", v->dec.scanning);

	v->dec.sampling_format = VBI_PIXFMT_YUV420;

	if (*services & ~(VBI_SLICED_VBI_525 | VBI_SLICED_VBI_625)) {
		*services = vbi_raw_decoder_add_services (&v->dec, *services, strict);

		if (*services == 0) {
			asprintf(errstr, _("Sorry, %s (%s) cannot "
					   "capture any of "
					   "the requested data services."),
				 dev_name, driver_name);
			goto failure;
		}

		v->sliced_buffer.data =
			malloc((v->dec.count[0] + v->dec.count[1])
			       * sizeof(vbi_sliced));

		if (!v->sliced_buffer.data) {
			asprintf(errstr, _("Virtual memory exhausted."));
			errno = ENOMEM;
			goto failure;
		}
	}

	printv("Will decode services 0x%08x\n", *services);

	/* Read mode */

	if (!v->select)
		printv("Warning: no read select, reading will block\n");

	v->capture.read = bktr_read;

	v->raw_buffer = calloc(1, sizeof(v->raw_buffer[0]));

	if (!v->raw_buffer) {
		asprintf(errstr, _("Virtual memory exhausted."));
		errno = ENOMEM;
		goto failure;
	}

	v->raw_buffer[0].size = (v->dec.count[0] + v->dec.count[1])
		* v->dec.bytes_per_line;

	v->raw_buffer[0].data = malloc(v->raw_buffer[0].size);

	if (!v->raw_buffer[0].data) {
		asprintf(errstr, _("Not enough memory to allocate "
				   "vbi capture buffer (%d KB)."),
			 (v->raw_buffer[0].size + 1023) >> 10);
		goto failure;
	}
Esempio n. 2
0
HRESULT DeckLinkCaptureDelegate::VideoInputFrameArrived( IDeckLinkVideoInputFrame *videoframe, IDeckLinkAudioInputPacket *audioframe )
{
    decklink_ctx_t *decklink_ctx = &decklink_opts_->decklink_ctx;
    obe_raw_frame_t *raw_frame = NULL;
    AVPacket pkt;
    AVFrame *frame = NULL;
    void *frame_bytes, *anc_line;
    obe_t *h = decklink_ctx->h;
    int finished = 0, ret, num_anc_lines = 0, anc_line_stride,
    lines_read = 0, first_line = 0, last_line = 0, line, num_vbi_lines, vii_line;
    uint32_t *frame_ptr;
    uint16_t *anc_buf, *anc_buf_pos;
    uint8_t *vbi_buf;
    int anc_lines[DECKLINK_VANC_LINES];
    IDeckLinkVideoFrameAncillary *ancillary;
    BMDTimeValue stream_time, frame_duration;

    if( decklink_opts_->probe_success )
        return S_OK;

    av_init_packet( &pkt );

    if( videoframe )
    {
        if( videoframe->GetFlags() & bmdFrameHasNoInputSource )
        {
            syslog( LOG_ERR, "Decklink card index %i: No input signal detected", decklink_opts_->card_idx );
            return S_OK;
        }
        else if( decklink_opts_->probe )
            decklink_opts_->probe_success = 1;

        /* use SDI ticks as clock source */
        videoframe->GetStreamTime( &stream_time, &frame_duration, OBE_CLOCK );
        obe_clock_tick( h, (int64_t)stream_time );

        if( decklink_ctx->last_frame_time == -1 )
            decklink_ctx->last_frame_time = obe_mdate();
        else
        {
            int64_t cur_frame_time = obe_mdate();
            if( cur_frame_time - decklink_ctx->last_frame_time >= SDI_MAX_DELAY )
            {
                syslog( LOG_WARNING, "Decklink card index %i: No frame received for %"PRIi64" ms", decklink_opts_->card_idx,
                       (cur_frame_time - decklink_ctx->last_frame_time) / 1000 );
                pthread_mutex_lock( &h->drop_mutex );
                h->encoder_drop = h->mux_drop = 1;
                pthread_mutex_unlock( &h->drop_mutex );
            }

            decklink_ctx->last_frame_time = cur_frame_time;
        }

        const int width = videoframe->GetWidth();
        const int height = videoframe->GetHeight();
        const int stride = videoframe->GetRowBytes();

        videoframe->GetBytes( &frame_bytes );

        /* TODO: support format switching (rare in SDI) */
        int j;
        for( j = 0; first_active_line[j].format != -1; j++ )
        {
            if( decklink_opts_->video_format == first_active_line[j].format )
                break;
        }

        videoframe->GetAncillaryData( &ancillary );

        /* NTSC starts on line 4 */
        line = decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC ? 4 : 1;
        anc_line_stride = FFALIGN( (width * 2 * sizeof(uint16_t)), 16 );

        /* Overallocate slightly for VANC buffer
         * Some VBI services stray into the active picture so allocate some extra space */
        anc_buf = anc_buf_pos = (uint16_t*)av_malloc( DECKLINK_VANC_LINES * anc_line_stride );
        if( !anc_buf )
        {
            syslog( LOG_ERR, "Malloc failed\n" );
            goto end;
        }

        while( 1 )
        {
            /* Some cards have restrictions on what lines can be accessed so try them all
             * Some buggy decklink cards will randomly refuse access to a particular line so
             * work around this issue by blanking the line */
            if( ancillary->GetBufferForVerticalBlankingLine( line, &anc_line ) == S_OK )
                decklink_ctx->unpack_line( (uint32_t*)anc_line, anc_buf_pos, width );
            else
                decklink_ctx->blank_line( anc_buf_pos, width );

            anc_buf_pos += anc_line_stride / 2;
            anc_lines[num_anc_lines++] = line;

            if( !first_line )
                first_line = line;
            last_line = line;

            lines_read++;
            line = sdi_next_line( decklink_opts_->video_format, line );

            if( line == first_active_line[j].line )
                break;
        }

        ancillary->Release();

        if( !decklink_opts_->probe )
        {
            raw_frame = new_raw_frame();
            if( !raw_frame )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                goto end;
            }
        }

        anc_buf_pos = anc_buf;
        for( int i = 0; i < num_anc_lines; i++ )
        {
            parse_vanc_line( h, &decklink_ctx->non_display_parser, raw_frame, anc_buf_pos, width, anc_lines[i] );
            anc_buf_pos += anc_line_stride / 2;
        }

        if( IS_SD( decklink_opts_->video_format ) && first_line != last_line )
        {
            /* Add a some VBI lines to the ancillary buffer */
            frame_ptr = (uint32_t*)frame_bytes;

            /* NTSC starts from line 283 so add an extra line */
            num_vbi_lines = NUM_ACTIVE_VBI_LINES + ( decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC );
            for( int i = 0; i < num_vbi_lines; i++ )
            {
                decklink_ctx->unpack_line( frame_ptr, anc_buf_pos, width );
                anc_buf_pos += anc_line_stride / 2;
                frame_ptr += stride / 4;
                last_line = sdi_next_line( decklink_opts_->video_format, last_line );
            }
            num_anc_lines += num_vbi_lines;

            vbi_buf = (uint8_t*)av_malloc( width * 2 * num_anc_lines );
            if( !vbi_buf )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                goto end;
            }

            /* Scale the lines from 10-bit to 8-bit */
            decklink_ctx->downscale_line( anc_buf, vbi_buf, num_anc_lines );
            anc_buf_pos = anc_buf;

            /* Handle Video Index information */
            int tmp_line = first_line;
            vii_line = decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC ? NTSC_VIDEO_INDEX_LINE : PAL_VIDEO_INDEX_LINE;
            while( tmp_line < vii_line )
            {
                anc_buf_pos += anc_line_stride / 2;
                tmp_line++;
            }

            if( decode_video_index_information( h, &decklink_ctx->non_display_parser, anc_buf_pos, raw_frame, vii_line ) < 0 )
                goto fail;

            if( !decklink_ctx->has_setup_vbi )
            {
                vbi_raw_decoder_init( &decklink_ctx->non_display_parser.vbi_decoder );

                decklink_ctx->non_display_parser.ntsc = decklink_opts_->video_format == INPUT_VIDEO_FORMAT_NTSC;
                decklink_ctx->non_display_parser.vbi_decoder.start[0] = first_line;
                decklink_ctx->non_display_parser.vbi_decoder.start[1] = sdi_next_line( decklink_opts_->video_format, first_line );
                decklink_ctx->non_display_parser.vbi_decoder.count[0] = last_line - decklink_ctx->non_display_parser.vbi_decoder.start[1] + 1;
                decklink_ctx->non_display_parser.vbi_decoder.count[1] = decklink_ctx->non_display_parser.vbi_decoder.count[0];

                if( setup_vbi_parser( &decklink_ctx->non_display_parser ) < 0 )
                    goto fail;

                decklink_ctx->has_setup_vbi = 1;
            }

            if( decode_vbi( h, &decklink_ctx->non_display_parser, vbi_buf, raw_frame ) < 0 )
                goto fail;

            av_free( vbi_buf );
        }

        av_free( anc_buf );

        if( !decklink_opts_->probe )
        {
            frame = avcodec_alloc_frame();
            if( !frame )
            {
                syslog( LOG_ERR, "[decklink]: Could not allocate video frame\n" );
                goto end;
            }
            decklink_ctx->codec->width = width;
            decklink_ctx->codec->height = height;

            pkt.data = (uint8_t*)frame_bytes;
            pkt.size = stride * height;

            ret = avcodec_decode_video2( decklink_ctx->codec, frame, &finished, &pkt );
            if( ret < 0 || !finished )
            {
                syslog( LOG_ERR, "[decklink]: Could not decode video frame\n" );
                goto end;
            }

            raw_frame->release_data = obe_release_video_data;
            raw_frame->release_frame = obe_release_frame;

            memcpy( raw_frame->alloc_img.stride, frame->linesize, sizeof(raw_frame->alloc_img.stride) );
            memcpy( raw_frame->alloc_img.plane, frame->data, sizeof(raw_frame->alloc_img.plane) );
            avcodec_free_frame( &frame );
            raw_frame->alloc_img.csp = (int)decklink_ctx->codec->pix_fmt;
            raw_frame->alloc_img.planes = av_pix_fmt_descriptors[raw_frame->alloc_img.csp].nb_components;
            raw_frame->alloc_img.width = width;
            raw_frame->alloc_img.height = height;
            raw_frame->alloc_img.format = decklink_opts_->video_format;
            raw_frame->timebase_num = decklink_opts_->timebase_num;
            raw_frame->timebase_den = decklink_opts_->timebase_den;

            memcpy( &raw_frame->img, &raw_frame->alloc_img, sizeof(raw_frame->alloc_img) );
            if( IS_SD( decklink_opts_->video_format ) )
            {
                if( raw_frame->alloc_img.height == 486 )
                    raw_frame->img.height = 480;

                raw_frame->img.first_line = first_active_line[j].line;
            }

            /* If AFD is present and the stream is SD this will be changed in the video filter */
            raw_frame->sar_width = raw_frame->sar_height = 1;
            raw_frame->pts = stream_time;

            for( int i = 0; i < decklink_ctx->device->num_input_streams; i++ )
            {
                if( decklink_ctx->device->streams[i]->stream_format == VIDEO_UNCOMPRESSED )
                    raw_frame->input_stream_id = decklink_ctx->device->streams[i]->input_stream_id;
            }

            if( add_to_filter_queue( h, raw_frame ) < 0 )
                goto fail;

            if( send_vbi_and_ttx( h, &decklink_ctx->non_display_parser, raw_frame->pts ) < 0 )
                goto fail;

            decklink_ctx->non_display_parser.num_vbi = 0;
            decklink_ctx->non_display_parser.num_anc_vbi = 0;
        }
    }

    /* TODO: probe SMPTE 337M audio */

    if( audioframe && !decklink_opts_->probe )
    {
        audioframe->GetBytes( &frame_bytes );
        raw_frame = new_raw_frame();
        if( !raw_frame )
        {
            syslog( LOG_ERR, "Malloc failed\n" );
            goto end;
        }

        raw_frame->audio_frame.num_samples = audioframe->GetSampleFrameCount();
        raw_frame->audio_frame.num_channels = decklink_opts_->num_channels;
        raw_frame->audio_frame.sample_fmt = AV_SAMPLE_FMT_S32P;

        if( av_samples_alloc( raw_frame->audio_frame.audio_data, &raw_frame->audio_frame.linesize, decklink_opts_->num_channels,
                              raw_frame->audio_frame.num_samples, (AVSampleFormat)raw_frame->audio_frame.sample_fmt, 0 ) < 0 )
        {
            syslog( LOG_ERR, "Malloc failed\n" );
            return -1;
        }

        if( avresample_convert( decklink_ctx->avr, raw_frame->audio_frame.audio_data, raw_frame->audio_frame.linesize,
                                raw_frame->audio_frame.num_samples, (uint8_t**)&frame_bytes, 0, raw_frame->audio_frame.num_samples ) < 0 )
        {
            syslog( LOG_ERR, "[decklink] Sample format conversion failed\n" );
            return -1;
        }

        BMDTimeValue packet_time;
        audioframe->GetPacketTime( &packet_time, OBE_CLOCK );
        raw_frame->pts = packet_time;
        raw_frame->release_data = obe_release_audio_data;
        raw_frame->release_frame = obe_release_frame;
        for( int i = 0; i < decklink_ctx->device->num_input_streams; i++ )
        {
            if( decklink_ctx->device->streams[i]->stream_format == AUDIO_PCM )
                raw_frame->input_stream_id = decklink_ctx->device->streams[i]->input_stream_id;
        }

        if( add_to_filter_queue( decklink_ctx->h, raw_frame ) < 0 )
            goto fail;
    }

end:
    if( frame )
        avcodec_free_frame( &frame );

    av_free_packet( &pkt );

    return S_OK;

fail:

    if( raw_frame )
    {
        raw_frame->release_data( raw_frame );
        raw_frame->release_frame( raw_frame );
    }

    return S_OK;
}