[FFmpeg-devel] [PATCH v2] lavf/mxfdec: demux s436m as eia608 subtitle track
Baptiste Coudurier
baptiste.coudurier at gmail.com
Thu Jul 5 01:05:58 EEST 2018
---
libavformat/mxfdec.c | 103 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index 575126d639..13226333cc 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -52,6 +52,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/parseutils.h"
#include "libavutil/timecode.h"
+#include "libavutil/opt.h"
#include "avformat.h"
#include "internal.h"
#include "mxf.h"
@@ -265,6 +266,7 @@ typedef struct MXFIndexTable {
} MXFIndexTable;
typedef struct MXFContext {
+ const AVClass *class; /**< Class for private options. */
MXFPartition *partitions;
unsigned partitions_count;
MXFOP op;
@@ -287,6 +289,7 @@ typedef struct MXFContext {
int last_forward_partition;
int nb_index_tables;
MXFIndexTable *index_tables;
+ int eia608_extract;
} MXFContext;
/* NOTE: klv_offset is not set (-1) for local keys */
@@ -449,6 +452,78 @@ static int find_body_sid_by_offset(MXFContext *mxf, int64_t offset)
return mxf->partitions[a].body_sid;
}
+static int mxf_get_eia608_packet(AVFormatContext *s, AVStream *st, AVPacket *pkt, int64_t length)
+{
+ int count = avio_rb16(s->pb);
+ int i, ret;
+
+ for (i = 0; i < count; i++) {
+ if (length < 6) {
+ av_log(s, AV_LOG_ERROR, "error reading s436m packet %"PRId64"\n", length);
+ return AVERROR_INVALIDDATA;
+ }
+ int line_num = avio_rb16(s->pb);
+ int wrapping_type = avio_r8(s->pb);
+ int sample_coding = avio_r8(s->pb);
+ int sample_count = avio_rb16(s->pb);
+ av_log(s, AV_LOG_DEBUG, "len %"PRId64" line %d wrap type %d coding %d count %d\n",
+ length, line_num, wrapping_type, sample_coding, sample_count);
+ length -= 6 + 8 + sample_count;
+ if (line_num != 9 && line_num != 11)
+ break;
+ if (sample_coding == 7 || sample_coding == 8 || sample_coding == 9) {
+ av_log(s, AV_LOG_ERROR, "unsupported s436m 10 bit sample coding\n");
+ return 0;
+ }
+ if (length < 0)
+ return AVERROR_INVALIDDATA;
+
+ int array_count = avio_rb32(s->pb);
+ int array_elem_size = avio_rb32(s->pb);
+ av_log(s, AV_LOG_DEBUG, "array count %d elem size %d\n", array_count, array_elem_size);
+ int did = avio_r8(s->pb);
+ int sdid = avio_r8(s->pb);
+ int data_count = avio_r8(s->pb);
+ av_log(s, AV_LOG_DEBUG, "did %x sdid %x count %d\n", did, sdid, data_count);
+ if (did != 0x61)
+ break;
+ int cdp_id = avio_rb16(s->pb);
+ int cdp_data_count = avio_r8(s->pb);
+ int cdp_framing_rate = avio_r8(s->pb) >> 4;
+ int cdp_flags = avio_r8(s->pb);
+ int cdp_counter = avio_rb16(s->pb);
+ int cdp_data_section = avio_r8(s->pb);
+ if (cdp_data_section != 0x72) {
+ av_log(s, AV_LOG_ERROR, "wrong cdp data section %x\n", cdp_data_section);
+ return AVERROR_INVALIDDATA;
+ }
+ int flags = avio_r8(s->pb);
+ int cc_count = flags & 0x1f;
+ av_log(s, AV_LOG_DEBUG, "cdp id %x dcount %d frame rate %d cdp flags %x flags %x "
+ "cc count %d counter %d section %x\n", cdp_id, cdp_data_count, cdp_framing_rate,
+ cdp_flags, flags, cc_count, cdp_counter, cdp_data_section);
+ ret = av_get_packet(s->pb, pkt, cc_count * 3);
+ if (ret < 0)
+ return ret;
+ if (cdp_data_count - 9 - 4 < cc_count * 3) {
+ av_log(s, AV_LOG_ERROR, "wrong cdp size %d cc count %d\n", data_count, cc_count);
+ return AVERROR_INVALIDDATA;
+ }
+ avio_skip(s->pb, data_count - 9 - 4 - cc_count * 3);
+ int cdp_footer_section = avio_r8(s->pb);
+ if (cdp_footer_section != 0x74) {
+ av_log(s, AV_LOG_ERROR, "wrong cdp footer section %x\n", cdp_footer_section);
+ return AVERROR_INVALIDDATA;
+ }
+ int cdp_counter2 = avio_rb16(s->pb);
+ int cdp_checksum = avio_r8(s->pb);
+ av_log(s, AV_LOG_DEBUG, "cdp counter %d checksum %x\n", cdp_counter2, cdp_checksum);
+ break;
+ }
+
+ return 0;
+}
+
/* XXX: use AVBitStreamFilter */
static int mxf_get_d10_aes3_packet(AVIOContext *pb, AVStream *st, AVPacket *pkt, int64_t length)
{
@@ -2424,6 +2499,11 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
st->codecpar->codec_type = type;
if (container_ul->desc)
av_dict_set(&st->metadata, "data_type", container_ul->desc, 0);
+ if (mxf->eia608_extract &&
+ !strcmp(container_ul->desc, "vbi_vanc_smpte_436M")) {
+ st->codecpar->codec_type = AVMEDIA_TYPE_SUBTITLE;
+ st->codecpar->codec_id = AV_CODEC_ID_EIA_608;
+ }
}
if (descriptor->extradata) {
if (!ff_alloc_extradata(st->codecpar, descriptor->extradata_size)) {
@@ -3396,6 +3476,13 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
mxf->current_klv_data = (KLVPacket){{0}};
return ret;
}
+ } else if (mxf->eia608_extract &&
+ s->streams[index]->codecpar->codec_id == AV_CODEC_ID_EIA_608) {
+ ret = mxf_get_eia608_packet(s, s->streams[index], pkt, klv.length);
+ if (ret < 0) {
+ mxf->current_klv_data = (KLVPacket){{0}};
+ return ret;
+ }
} else {
ret = av_get_packet(s->pb, pkt, klv.length);
if (ret < 0) {
@@ -3594,6 +3681,21 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
return 0;
}
+static const AVOption options[] = {
+ { "eia608_extract", "extract eia 608 captions from s436m track",
+ offsetof(MXFContext, eia608_extract), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1,
+ AV_OPT_FLAG_DECODING_PARAM },
+ { NULL },
+};
+
+static const AVClass demuxer_class = {
+ .class_name = "mxf",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .category = AV_CLASS_CATEGORY_DEMUXER,
+};
+
AVInputFormat ff_mxf_demuxer = {
.name = "mxf",
.long_name = NULL_IF_CONFIG_SMALL("MXF (Material eXchange Format)"),
@@ -3604,4 +3706,5 @@ AVInputFormat ff_mxf_demuxer = {
.read_packet = mxf_read_packet,
.read_close = mxf_read_close,
.read_seek = mxf_read_seek,
+ .priv_class = &demuxer_class,
};
--
2.17.0 (Apple Git-106)
More information about the ffmpeg-devel
mailing list