summaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorClément Bœsch <clement.boesch@smartjog.com>2012-05-30 10:26:53 +0200
committerClément Bœsch <ubitux@gmail.com>2012-06-04 07:41:22 +0200
commit6b35f1a2a6432cb79f657ea3fadb86b8e12dddcb (patch)
tree372b3d3ee1664494f32d1b518caf54fb9c4dd20b /libavformat
parent0f0f3bd1e022639eb8e9c02b7b18f37071c21763 (diff)
downloadffmpeg-streaming-6b35f1a2a6432cb79f657ea3fadb86b8e12dddcb.zip
ffmpeg-streaming-6b35f1a2a6432cb79f657ea3fadb86b8e12dddcb.tar.gz
timecode: move timecode muxer options to metadata.
Some demuxers set a timecode in the format or streams metadata. The muxers now make use of this metadata instead of a duplicated private option. This makes possible transparent copy of the timecode when transmuxing and transcoding. -timecode option for MPEG1/2 codec is also renamed to -gop_timecode. The global ffmpeg -timecode option will set it anyway so no option change visible for the user.
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/dvenc.c26
-rw-r--r--libavformat/gxfenc.c26
-rw-r--r--libavformat/mxfenc.c31
3 files changed, 23 insertions, 60 deletions
diff --git a/libavformat/dvenc.c b/libavformat/dvenc.c
index 506225e..f3056f7 100644
--- a/libavformat/dvenc.c
+++ b/libavformat/dvenc.c
@@ -52,7 +52,6 @@ struct DVMuxContext {
int has_audio; /* frame under contruction has audio */
int has_video; /* frame under contruction has video */
uint8_t frame_buf[DV_MAX_FRAME_SIZE]; /* frame under contruction */
- char *tc_opt_str; /* timecode option string */
AVTimecode tc; /* timecode context */
};
@@ -356,6 +355,7 @@ static int dv_write_header(AVFormatContext *s)
{
AVRational rate;
DVMuxContext *dvc = s->priv_data;
+ AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
if (!dv_init_mux(s)) {
av_log(s, AV_LOG_ERROR, "Can't initialize DV format!\n"
@@ -366,9 +366,16 @@ static int dv_write_header(AVFormatContext *s)
}
rate.num = dvc->sys->ltc_divisor;
rate.den = 1;
- if (dvc->tc_opt_str)
- return av_timecode_init_from_string(&dvc->tc, rate,
- dvc->tc_opt_str, s);
+ if (!tcr) { // no global timecode, look into the streams
+ int i;
+ for (i = 0; i < s->nb_streams; i++) {
+ tcr = av_dict_get(s->streams[i]->metadata, "timecode", NULL, 0);
+ if (tcr)
+ break;
+ }
+ }
+ if (tcr)
+ return av_timecode_init_from_string(&dvc->tc, rate, tcr->value, s);
return av_timecode_init(&dvc->tc, rate, 0, 0, s);
}
@@ -398,16 +405,6 @@ static int dv_write_trailer(struct AVFormatContext *s)
return 0;
}
-static const AVClass class = {
- .class_name = "dv",
- .item_name = av_default_item_name,
- .version = LIBAVUTIL_VERSION_INT,
- .option = (const AVOption[]){
- {AV_TIMECODE_OPTION(DVMuxContext, tc_opt_str, AV_OPT_FLAG_ENCODING_PARAM)},
- {NULL},
- },
-};
-
AVOutputFormat ff_dv_muxer = {
.name = "dv",
.long_name = NULL_IF_CONFIG_SMALL("DV video format"),
@@ -418,5 +415,4 @@ AVOutputFormat ff_dv_muxer = {
.write_header = dv_write_header,
.write_packet = dv_write_packet,
.write_trailer = dv_write_trailer,
- .priv_class = &class,
};
diff --git a/libavformat/gxfenc.c b/libavformat/gxfenc.c
index 089a689..3c5078c 100644
--- a/libavformat/gxfenc.c
+++ b/libavformat/gxfenc.c
@@ -41,7 +41,6 @@ typedef struct GXFTimecode{
int ff;
int color;
int drop;
- char *str;
} GXFTimecode;
typedef struct GXFStreamContext {
@@ -655,11 +654,11 @@ static void gxf_init_timecode_track(GXFStreamContext *sc, GXFStreamContext *vsc)
sc->fields = vsc->fields;
}
-static int gxf_init_timecode(AVFormatContext *s, GXFTimecode *tc, int fields)
+static int gxf_init_timecode(AVFormatContext *s, GXFTimecode *tc, const char *tcstr, int fields)
{
char c;
- if (sscanf(tc->str, "%d:%d:%d%c%d", &tc->hh, &tc->mm, &tc->ss, &c, &tc->ff) != 5) {
+ if (sscanf(tcstr, "%d:%d:%d%c%d", &tc->hh, &tc->mm, &tc->ss, &c, &tc->ff) != 5) {
av_log(s, AV_LOG_ERROR, "unable to parse timecode, "
"syntax: hh:mm:ss[:;.]ff\n");
return -1;
@@ -681,6 +680,7 @@ static int gxf_write_header(AVFormatContext *s)
GXFStreamContext *vsc = NULL;
uint8_t tracks[255] = {0};
int i, media_info = 0;
+ AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
if (!pb->seekable) {
av_log(s, AV_LOG_ERROR, "gxf muxer does not support streamed output, patch welcome");
@@ -741,6 +741,8 @@ static int gxf_write_header(AVFormatContext *s)
"gxf muxer only accepts PAL or NTSC resolutions currently\n");
return -1;
}
+ if (!tcr)
+ tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
avpriv_set_pts_info(st, 64, gxf->time_base.num, gxf->time_base.den);
if (gxf_find_lines_index(st) < 0)
sc->lines_index = -1;
@@ -792,9 +794,8 @@ static int gxf_write_header(AVFormatContext *s)
if (ff_audio_interleave_init(s, GXF_samples_per_frame, (AVRational){ 1, 48000 }) < 0)
return -1;
- if (gxf->tc.str) {
- gxf_init_timecode(s, &gxf->tc, vsc->fields);
- }
+ if (tcr)
+ gxf_init_timecode(s, &gxf->tc, tcr->value, vsc->fields);
gxf_init_timecode_track(&gxf->timecode_track, vsc);
gxf->flags |= 0x200000; // time code track is non-drop frame
@@ -983,18 +984,6 @@ static int gxf_interleave_packet(AVFormatContext *s, AVPacket *out, AVPacket *pk
ff_interleave_packet_per_dts, gxf_compare_field_nb);
}
-static const AVOption options[] = {
- { AV_TIMECODE_OPTION(GXFContext, tc.str, AV_OPT_FLAG_ENCODING_PARAM) },
- { NULL }
-};
-
-static const AVClass gxf_muxer_class = {
- .class_name = "GXF muxer",
- .item_name = av_default_item_name,
- .option = options,
- .version = LIBAVUTIL_VERSION_INT,
-};
-
AVOutputFormat ff_gxf_muxer = {
.name = "gxf",
.long_name = NULL_IF_CONFIG_SMALL("GXF format"),
@@ -1006,5 +995,4 @@ AVOutputFormat ff_gxf_muxer = {
.write_packet = gxf_write_packet,
.write_trailer = gxf_write_trailer,
.interleave_packet = gxf_interleave_packet,
- .priv_class = &gxf_muxer_class,
};
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index f87a50a..b2fe736 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -189,7 +189,6 @@ typedef struct MXFContext {
unsigned body_partitions_count;
int last_key_index; ///< index of last key frame
uint64_t duration;
- char *tc_opt_str; ///< timecode option string
AVTimecode tc; ///< timecode context
AVStream *timecode_track;
int timecode_base; ///< rounded time code base (25 or 30)
@@ -1403,6 +1402,7 @@ static int mxf_write_header(AVFormatContext *s)
const int *samples_per_frame = NULL;
AVDictionaryEntry *t;
int64_t timestamp = 0;
+ AVDictionaryEntry *tcr = av_dict_get(s->metadata, "timecode", NULL, 0);
if (!s->nb_streams)
return -1;
@@ -1443,9 +1443,10 @@ static int mxf_write_header(AVFormatContext *s)
}
rate = (AVRational){mxf->time_base.den, mxf->time_base.num};
avpriv_set_pts_info(st, 64, mxf->time_base.num, mxf->time_base.den);
- if (mxf->tc_opt_str)
- ret = av_timecode_init_from_string(&mxf->tc, rate,
- mxf->tc_opt_str, s);
+ if (!tcr)
+ tcr = av_dict_get(st->metadata, "timecode", NULL, 0);
+ if (tcr)
+ ret = av_timecode_init_from_string(&mxf->tc, rate, tcr->value, s);
else
ret = av_timecode_init(&mxf->tc, rate, 0, 0, s);
if (ret < 0)
@@ -1877,26 +1878,6 @@ static int mxf_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int
mxf_interleave_get_packet, mxf_compare_timestamps);
}
-static const AVClass mxf_class = {
- .class_name = "mxf",
- .item_name = av_default_item_name,
- .version = LIBAVUTIL_VERSION_INT,
- .option = (const AVOption[]){
- {AV_TIMECODE_OPTION(MXFContext, tc_opt_str, AV_OPT_FLAG_ENCODING_PARAM)},
- {NULL}
- },
-};
-
-static const AVClass mxf_d10_class = {
- .class_name = "mxf_d10",
- .item_name = av_default_item_name,
- .version = LIBAVUTIL_VERSION_INT,
- .option = (const AVOption[]){
- {AV_TIMECODE_OPTION(MXFContext, tc_opt_str, AV_OPT_FLAG_ENCODING_PARAM)},
- {NULL}
- },
-};
-
AVOutputFormat ff_mxf_muxer = {
.name = "mxf",
.long_name = NULL_IF_CONFIG_SMALL("Material eXchange Format"),
@@ -1910,7 +1891,6 @@ AVOutputFormat ff_mxf_muxer = {
.write_trailer = mxf_write_footer,
.flags = AVFMT_NOTIMESTAMPS,
.interleave_packet = mxf_interleave,
- .priv_class = &mxf_class,
};
AVOutputFormat ff_mxf_d10_muxer = {
@@ -1925,5 +1905,4 @@ AVOutputFormat ff_mxf_d10_muxer = {
.write_trailer = mxf_write_footer,
.flags = AVFMT_NOTIMESTAMPS,
.interleave_packet = mxf_interleave,
- .priv_class = &mxf_d10_class,
};
OpenPOWER on IntegriCloud