Signed-off-by: Marton Balint <c...@passwd.hu> --- doc/indevs.texi | 9 +++++++ libavdevice/Makefile | 2 +- libavdevice/decklink_common.h | 2 ++ libavdevice/decklink_common_c.h | 1 + libavdevice/decklink_dec.cpp | 56 +++++++++++++++++++++++++++++++++++++++++ libavdevice/decklink_dec_c.c | 3 +++ 6 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/doc/indevs.texi b/doc/indevs.texi index 6cf626d..54ab824 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -236,6 +236,15 @@ Defaults to @option{false}. If set to @samp{1}, video is captured in 10 bit v210 instead of uyvy422. Not all Blackmagic devices support this option. +@item teletext_lines +If set to nonzero, an additional teletext stream will be captured from the +vertical ancillary data. This option is a bitmask of the VBI lines checked, +specifically lines 6 to 22, and lines 318 to 335. Line 6 is the LSB in the mask. +Selected lines which do not contain teletext information will be ignored. You +can use the special @option{all} constant to select all possible lines, or +@option{standard} to skip lines 6, 318 and 319, which are not compatible with all +receivers. Capturing teletext only works for SD PAL sources in 8 bit mode. + @end table @subsection Examples diff --git a/libavdevice/Makefile b/libavdevice/Makefile index f889b7c..4710d79 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -16,7 +16,7 @@ OBJS-$(CONFIG_AVFOUNDATION_INDEV) += avfoundation.o OBJS-$(CONFIG_BKTR_INDEV) += bktr.o OBJS-$(CONFIG_CACA_OUTDEV) += caca.o OBJS-$(CONFIG_DECKLINK_OUTDEV) += decklink_enc.o decklink_enc_c.o decklink_common.o -OBJS-$(CONFIG_DECKLINK_INDEV) += decklink_dec.o decklink_dec_c.o decklink_common.o +OBJS-$(CONFIG_DECKLINK_INDEV) += decklink_dec.o decklink_dec_c.o decklink_common.o teletext_quantizer.o OBJS-$(CONFIG_DSHOW_INDEV) += dshow_crossbar.o dshow.o dshow_enummediatypes.o \ dshow_enumpins.o dshow_filter.o \ dshow_pin.o dshow_common.o diff --git a/libavdevice/decklink_common.h b/libavdevice/decklink_common.h index 3bc30f0..076c625 100644 --- a/libavdevice/decklink_common.h +++ b/libavdevice/decklink_common.h @@ -67,10 +67,12 @@ struct decklink_ctx { unsigned int dropped; AVStream *audio_st; AVStream *video_st; + AVStream *teletext_st; /* Options */ int list_devices; int list_formats; + int64_t teletext_lines; double preroll; int frames_preroll; diff --git a/libavdevice/decklink_common_c.h b/libavdevice/decklink_common_c.h index fb2b788..2b1a579 100644 --- a/libavdevice/decklink_common_c.h +++ b/libavdevice/decklink_common_c.h @@ -27,6 +27,7 @@ struct decklink_cctx { /* Options */ int list_devices; int list_formats; + int64_t teletext_lines; double preroll; int v210; }; diff --git a/libavdevice/decklink_dec.cpp b/libavdevice/decklink_dec.cpp index 89f93de..d123c4a 100644 --- a/libavdevice/decklink_dec.cpp +++ b/libavdevice/decklink_dec.cpp @@ -28,6 +28,7 @@ extern "C" { #include "libavformat/avformat.h" #include "libavformat/internal.h" #include "libavutil/imgutils.h" +#include "libavdevice/teletext_quantizer.h" } #include "decklink_common.h" @@ -277,6 +278,46 @@ HRESULT decklink_input_callback::VideoInputFrameArrived( pkt.size = videoFrame->GetRowBytes() * videoFrame->GetHeight(); //fprintf(stderr,"Video Frame size %d ts %d\n", pkt.size, pkt.pts); + + if (!no_video && ctx->teletext_lines && videoFrame->GetPixelFormat() == bmdFormat8BitYUV && videoFrame->GetWidth() == 720) { + IDeckLinkVideoFrameAncillary *vanc; + AVPacket txt_pkt; + uint8_t txt_buf[1611]; // max 35 * 46 bytes decoded teletext lines + 1 byte data_identifier + uint8_t *txt_data = txt_buf; + + if (videoFrame->GetAncillaryData(&vanc) == S_OK) { + int stuffing_units, i; + int64_t line_mask = 1; + av_init_packet(&txt_pkt); + txt_pkt.pts = pkt.pts; + txt_pkt.dts = pkt.dts; + txt_pkt.stream_index = ctx->teletext_st->index; + txt_pkt.data = txt_data; + txt_data[0] = 0x10; // data_identifier - EBU_data + txt_data++; + for (i = 6; i < 336; i++, line_mask <<= 1) { + uint8_t *buf; + if ((ctx->teletext_lines & line_mask) && vanc->GetBufferForVerticalBlankingLine(i, (void**)&buf) == S_OK) { + if (ff_teletext_line_from_vbi_data(i, buf, txt_data) >= 0) + txt_data += 46; + } + if (i == 22) + i = 317; + } + vanc->Release(); + stuffing_units = (4 - ((45 + txt_data - txt_pkt.data) / 46) % 4) % 4; + while (stuffing_units--) { + memset(txt_data, 0xff, 46); + txt_data[1] = 0x2c; // data_unit_length + txt_data += 46; + } + txt_pkt.size = txt_data - txt_pkt.data; + if (avpacket_queue_put(&ctx->queue, &txt_pkt) < 0) { + ++ctx->dropped; + } + } + } + c->frame_number++; if (avpacket_queue_put(&ctx->queue, &pkt) < 0) { ++ctx->dropped; @@ -378,6 +419,7 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) 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; cctx->ctx = ctx; @@ -488,6 +530,20 @@ av_cold int ff_decklink_read_header(AVFormatContext *avctx) 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"); + goto error; + } + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + st->codec->time_base.den = ctx->bmd_tb_den; + st->codec->time_base.num = ctx->bmd_tb_num; + st->codec->codec_id = AV_CODEC_ID_DVB_TELETEXT; + avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ + ctx->teletext_st = st; + } + result = ctx->dli->EnableAudioInput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2); if (result != S_OK) { diff --git a/libavdevice/decklink_dec_c.c b/libavdevice/decklink_dec_c.c index b1a65e6..e5d6bc0 100644 --- a/libavdevice/decklink_dec_c.c +++ b/libavdevice/decklink_dec_c.c @@ -32,6 +32,9 @@ static const AVOption options[] = { { "list_devices", "list available devices" , OFFSET(list_devices), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, DEC }, { "list_formats", "list supported formats" , OFFSET(list_formats), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, DEC }, { "bm_v210", "v210 10 bit per channel" , OFFSET(v210), AV_OPT_TYPE_INT , { .i64 = 0 }, 0, 1, DEC }, + { "teletext_lines", "teletext lines bitmask", OFFSET(teletext_lines), AV_OPT_TYPE_INT64, { .i64 = 0 }, 0, 0x7ffffffffLL, DEC, "teletext_lines"}, + { "standard", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7fff9fffeLL}, 0, 0, DEC, "teletext_lines"}, + { "all", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0x7ffffffffLL}, 0, 0, DEC, "teletext_lines"}, { NULL }, }; -- 2.6.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel