Skip to content
Snippets Groups Projects
decklink_dec.cpp 43.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
        ctx = (struct decklink_ctx *) av_mallocz(sizeof(struct decklink_ctx));
        if (!ctx)
            return AVERROR(ENOMEM);
        ctx->list_devices = cctx->list_devices;
        ctx->list_formats = cctx->list_formats;
    
        ctx->teletext_lines = cctx->teletext_lines;
    
        ctx->preroll      = cctx->preroll;
    
        ctx->duplex_mode  = cctx->duplex_mode;
    
        if (cctx->tc_format > 0 && (unsigned int)cctx->tc_format < FF_ARRAY_ELEMS(decklink_timecode_format_map))
            ctx->tc_format = decklink_timecode_format_map[cctx->tc_format];
    
        if (cctx->video_input > 0 && (unsigned int)cctx->video_input < FF_ARRAY_ELEMS(decklink_video_connection_map))
            ctx->video_input = decklink_video_connection_map[cctx->video_input];
        if (cctx->audio_input > 0 && (unsigned int)cctx->audio_input < FF_ARRAY_ELEMS(decklink_audio_connection_map))
            ctx->audio_input = decklink_audio_connection_map[cctx->audio_input];
    
        ctx->audio_pts_source = cctx->audio_pts_source;
        ctx->video_pts_source = cctx->video_pts_source;
    
        ctx->audio_depth = cctx->audio_depth;
    
        cctx->ctx = ctx;
    
    
        /* Check audio channel option for valid values: 2, 8 or 16 */
        switch (cctx->audio_channels) {
            case 2:
            case 8:
            case 16:
                break;
            default:
                av_log(avctx, AV_LOG_ERROR, "Value of channels option must be one of 2, 8 or 16\n");
                return AVERROR(EINVAL);
        }
    
    
        /* Check audio bit depth option for valid values: 16 or 32 */
        switch (cctx->audio_depth) {
            case 16:
            case 32:
                break;
            default:
                av_log(avctx, AV_LOG_ERROR, "Value for audio bit depth option must be either 16 or 32\n");
                return AVERROR(EINVAL);
        }
    
    
        /* List available devices. */
        if (ctx->list_devices) {
    
            ff_decklink_list_devices_legacy(avctx, 1, 0);
    
            return AVERROR_EXIT;
        }
    
    
        if (cctx->v210) {
            av_log(avctx, AV_LOG_WARNING, "The bm_v210 option is deprecated and will be removed. Please use the -raw_format yuv422p10.\n");
            cctx->raw_format = MKBETAG('v','2','1','0');
        }
    
    
        av_strlcpy(fname, avctx->url, sizeof(fname));
    
        tmp=strchr (fname, '@');
        if (tmp != NULL) {
    
            av_log(avctx, AV_LOG_WARNING, "The @mode syntax is deprecated and will be removed. Please use the -format_code option.\n");
    
            mode_num = atoi (tmp+1);
            *tmp = 0;
        }
    
    
        ret = ff_decklink_init_device(avctx, fname);
        if (ret < 0)
            return ret;
    
    
        /* Get input device. */
        if (ctx->dl->QueryInterface(IID_IDeckLinkInput, (void **) &ctx->dli) != S_OK) {
    
            av_log(avctx, AV_LOG_ERROR, "Could not open input device from '%s'\n",
    
        }
    
        /* List supported formats. */
        if (ctx->list_formats) {
            ff_decklink_list_formats(avctx, DIRECTION_IN);
    
        if (ff_decklink_set_configs(avctx, DIRECTION_IN) < 0) {
            av_log(avctx, AV_LOG_ERROR, "Could not set input configuration\n");
            ret = AVERROR(EIO);
            goto error;
        }
    
    
        input_callback = new decklink_input_callback(avctx);
        ret = (ctx->dli->SetCallback(input_callback) == S_OK ? 0 : AVERROR_EXTERNAL);
        input_callback->Release();
        if (ret < 0) {
            av_log(avctx, AV_LOG_ERROR, "Cannot set input callback\n");
            goto error;
        }
    
        allocator = new decklink_allocator();
        ret = (ctx->dli->SetVideoInputFrameMemoryAllocator(allocator) == S_OK ? 0 : AVERROR_EXTERNAL);
        allocator->Release();
        if (ret < 0) {
            av_log(avctx, AV_LOG_ERROR, "Cannot set custom memory allocator\n");
            goto error;
        }
    
    
        if (mode_num == 0 && !cctx->format_code) {
            if (decklink_autodetect(cctx) < 0) {
                av_log(avctx, AV_LOG_ERROR, "Cannot Autodetect input stream or No signal\n");
    
            av_log(avctx, AV_LOG_INFO, "Autodetected the input mode\n");
        }
        if (ff_decklink_set_format(avctx, DIRECTION_IN, mode_num) < 0) {
            av_log(avctx, AV_LOG_ERROR, "Could not set mode number %d or format code %s for %s\n",
                mode_num, (cctx->format_code) ? cctx->format_code : "(unset)", fname);
            ret = AVERROR(EIO);
            goto error;
    
    #if !CONFIG_LIBZVBI
        if (ctx->teletext_lines && ctx->bmd_mode == bmdModePAL) {
            av_log(avctx, AV_LOG_ERROR, "Libzvbi support is needed for capturing SD PAL teletext, please recompile FFmpeg.\n");
            ret = AVERROR(ENOSYS);
            goto error;
        }
    #endif
    
    
        /* Setup streams. */
        st = avformat_new_stream(avctx, NULL);
        if (!st) {
            av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
    
        st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;
    
        st->codecpar->codec_id    = cctx->audio_depth == 32 ? AV_CODEC_ID_PCM_S32LE : AV_CODEC_ID_PCM_S16LE;
    
        st->codecpar->sample_rate = bmdAudioSampleRate48kHz;
        st->codecpar->channels    = cctx->audio_channels;
    
        avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
        ctx->audio_st=st;
    
        st = avformat_new_stream(avctx, NULL);
        if (!st) {
            av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
    
        st->codecpar->codec_type  = AVMEDIA_TYPE_VIDEO;
        st->codecpar->width       = ctx->bmd_width;
        st->codecpar->height      = ctx->bmd_height;
    
        st->time_base.den      = ctx->bmd_tb_den;
        st->time_base.num      = ctx->bmd_tb_num;
    
        st->r_frame_rate       = av_make_q(st->time_base.den, st->time_base.num);
    
        switch((BMDPixelFormat)cctx->raw_format) {
        case bmdFormat8BitYUV:
    
            st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
            st->codecpar->codec_tag   = MKTAG('U', 'Y', 'V', 'Y');
    
            st->codecpar->format      = AV_PIX_FMT_UYVY422;
    
            st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 16, st->time_base.den, st->time_base.num);
    
            break;
        case bmdFormat10BitYUV:
            st->codecpar->codec_id    = AV_CODEC_ID_V210;
            st->codecpar->codec_tag   = MKTAG('V','2','1','0');
            st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 64, st->time_base.den, st->time_base.num * 3);
            st->codecpar->bits_per_coded_sample = 10;
            break;
        case bmdFormat8BitARGB:
            st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
    
            st->codecpar->codec_tag   = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);
    
            st->codecpar->format      = AV_PIX_FMT_0RGB;
    
            st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num);
            break;
        case bmdFormat8BitBGRA:
            st->codecpar->codec_id    = AV_CODEC_ID_RAWVIDEO;
            st->codecpar->codec_tag   = avcodec_pix_fmt_to_codec_tag((enum AVPixelFormat)st->codecpar->format);
    
            st->codecpar->format      = AV_PIX_FMT_BGR0;
    
            st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 32, st->time_base.den, st->time_base.num);
            break;
        case bmdFormat10BitRGB:
            st->codecpar->codec_id    = AV_CODEC_ID_R210;
            st->codecpar->codec_tag   = MKTAG('R','2','1','0');
            st->codecpar->format      = AV_PIX_FMT_RGB48LE;
            st->codecpar->bit_rate    = av_rescale(ctx->bmd_width * ctx->bmd_height * 30, st->time_base.den, st->time_base.num);
            st->codecpar->bits_per_coded_sample = 10;
            break;
        default:
            av_log(avctx, AV_LOG_ERROR, "Raw Format %.4s not supported\n", (char*) &cctx->raw_format);
            ret = AVERROR(EINVAL);
            goto error;
    
        switch (ctx->bmd_field_dominance) {
        case bmdUpperFieldFirst:
            st->codecpar->field_order = AV_FIELD_TT;
            break;
        case bmdLowerFieldFirst:
            st->codecpar->field_order = AV_FIELD_BB;
            break;
        case bmdProgressiveFrame:
        case bmdProgressiveSegmentedFrame:
            st->codecpar->field_order = AV_FIELD_PROGRESSIVE;
            break;
        }
    
    
        avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
    
        ctx->video_st=st;
    
    
        if (ctx->teletext_lines) {
            st = avformat_new_stream(avctx, NULL);
            if (!st) {
                av_log(avctx, AV_LOG_ERROR, "Cannot add stream\n");
    
            st->codecpar->codec_type  = AVMEDIA_TYPE_SUBTITLE;
            st->time_base.den         = ctx->bmd_tb_den;
            st->time_base.num         = ctx->bmd_tb_num;
            st->codecpar->codec_id    = AV_CODEC_ID_DVB_TELETEXT;
    
            avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
            ctx->teletext_st = st;
        }
    
    
        av_log(avctx, AV_LOG_VERBOSE, "Using %d input audio channels\n", ctx->audio_st->codecpar->channels);
    
        result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, cctx->audio_depth == 32 ? bmdAudioSampleType32bitInteger : bmdAudioSampleType16bitInteger, ctx->audio_st->codecpar->channels);
    
    
        if (result != S_OK) {
            av_log(avctx, AV_LOG_ERROR, "Cannot enable audio input\n");
    
        result = ctx->dli->EnableVideoInput(ctx->bmd_mode,
    
                                            (BMDPixelFormat) cctx->raw_format,
    
    
        if (result != S_OK) {
            av_log(avctx, AV_LOG_ERROR, "Cannot enable video input\n");
    
            goto error;
        }
    
        avpacket_queue_init (avctx, &ctx->queue);
    
    
        if (ctx->dli->StartStreams() != S_OK) {
    
            av_log(avctx, AV_LOG_ERROR, "Cannot start input stream\n");
    
    }
    
    int ff_decklink_read_packet(AVFormatContext *avctx, AVPacket *pkt)
    {
    
        struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data;
        struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx;
    
    
        avpacket_queue_get(&ctx->queue, pkt, 1);
    
    
        if (ctx->tc_format && !(av_dict_get(ctx->video_st->metadata, "timecode", NULL, 0))) {
            int size;
            const uint8_t *side_metadata = av_packet_get_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, &size);
            if (side_metadata) {
               if (av_packet_unpack_dictionary(side_metadata, size, &ctx->video_st->metadata) < 0)
                   av_log(avctx, AV_LOG_ERROR, "Unable to set timecode\n");
            }
        }
    
    
    int ff_decklink_list_input_devices(AVFormatContext *avctx, struct AVDeviceInfoList *device_list)
    {
        return ff_decklink_list_devices(avctx, device_list, 1, 0);
    }
    
    
    } /* extern "C" */