[FFmpeg-devel] [PATCH] avformat/matroskaenc: Accept time base hint
Michael Bradshaw
mjbshaw at gmail.com
Wed Dec 28 07:47:47 EET 2016
From: Michael Bradshaw <mjbshaw at google.com>
Signed-off-by: Michael Bradshaw <mjbshaw at google.com>
---
libavformat/matroskaenc.c | 38 +++++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index 827d755..2c2c930 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -117,6 +117,7 @@ typedef struct mkv_attachments {
typedef struct MatroskaMuxContext {
const AVClass *class;
int mode;
+ int timecode_scale;
AVIOContext *dyn_bc;
AVIOContext *tags_bc;
ebml_master tags;
@@ -1757,7 +1758,7 @@ static int mkv_write_header(AVFormatContext *s)
return ret;
pb = mkv->info_bc;
- put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000);
+ put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, mkv->timecode_scale);
if ((tag = av_dict_get(s->metadata, "title", NULL, 0)))
put_ebml_string(pb, MATROSKA_ID_TITLE, tag->value);
if (!(s->flags & AVFMT_FLAG_BITEXACT)) {
@@ -1799,11 +1800,11 @@ static int mkv_write_header(AVFormatContext *s)
int64_t metadata_duration = get_metadata_duration(s);
if (s->duration > 0) {
- int64_t scaledDuration = av_rescale(s->duration, 1000, AV_TIME_BASE);
+ int64_t scaledDuration = av_rescale(s->duration, 1000000000, AV_TIME_BASE * (int64_t)mkv->timecode_scale);
put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);
av_log(s, AV_LOG_DEBUG, "Write early duration from recording time = %" PRIu64 "\n", scaledDuration);
} else if (metadata_duration > 0) {
- int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE);
+ int64_t scaledDuration = av_rescale(metadata_duration, 1000000000, AV_TIME_BASE * (int64_t)mkv->timecode_scale);
put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration);
av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration);
} else {
@@ -1864,12 +1865,12 @@ static int mkv_write_header(AVFormatContext *s)
// after 4k and on a keyframe
if (pb->seekable) {
if (mkv->cluster_time_limit < 0)
- mkv->cluster_time_limit = 5000;
+ mkv->cluster_time_limit = av_rescale(5, 1000000000, mkv->timecode_scale);
if (mkv->cluster_size_limit < 0)
mkv->cluster_size_limit = 5 * 1024 * 1024;
} else {
if (mkv->cluster_time_limit < 0)
- mkv->cluster_time_limit = 1000;
+ mkv->cluster_time_limit = 1000000000 / mkv->timecode_scale;
if (mkv->cluster_size_limit < 0)
mkv->cluster_size_limit = 32 * 1024;
}
@@ -2458,6 +2459,7 @@ static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance)
static int mkv_init(struct AVFormatContext *s)
{
+ MatroskaMuxContext *mkv = s->priv_data;
int i;
if (s->avoid_negative_ts < 0) {
@@ -2465,9 +2467,31 @@ static int mkv_init(struct AVFormatContext *s)
s->internal->avoid_negative_ts_use_pts = 1;
}
+ // ms precision is the de-facto standard timescale for mkv files
+ mkv->timecode_scale = 1000000;
+
+ // If the user has supplied a desired time base, use it if possible
+ if (s->nb_streams > 0) {
+ AVRational time_base = s->streams[0]->time_base;
+ for (i = 1; i < s->nb_streams; i++) {
+ if (time_base.num != s->streams[i]->time_base.num ||
+ time_base.den != s->streams[i]->time_base.den) {
+ time_base = av_make_q(0, 0);
+ break;
+ }
+ }
+ // Make sure the time base is valid, can losslessly be converted to
+ // nanoseconds, and isn't longer than 1 second
+ if (time_base.num > 0 &&
+ time_base.den > 0 &&
+ 1000000000 % time_base.den == 0 &&
+ time_base.num <= time_base.den) {
+ mkv->timecode_scale = (int)av_rescale(time_base.num, 1000000000, time_base.den);
+ }
+ }
+
for (i = 0; i < s->nb_streams; i++) {
- // ms precision is the de-facto standard timescale for mkv files
- avpriv_set_pts_info(s->streams[i], 64, 1, 1000);
+ avpriv_set_pts_info(s->streams[i], 64, mkv->timecode_scale, 1000000000);
}
return 0;
--
2.10.1 (Apple Git-78)
More information about the ffmpeg-devel
mailing list