[FFmpeg-devel] [PATCH] avformat/matroskaenc: Accept time base hint
Michael Niedermayer
michaelni at gmx.at
Sat Jan 14 13:57:43 EET 2017
On Tue, Dec 27, 2016 at 09:47:47PM -0800, Michael Bradshaw wrote:
> 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++) {
inconsistent indention
> + 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;
> + }
> + }
This looks just at one stream, what if other streams have other
timebases ?
you could pick a common tb so that timestamps in any of the requested
ones can be represented. While this wont always be possible due to
bits per int constraint i dont think completely ignoring other streams
is safe.
> + // 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);
assuming someone asks for 1001/24000 he would get something else
and something that is lower precission than what the default would
have been prior to this patch IIUC
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
it is not once nor twice but times without number that the same ideas make
their appearance in the world. -- Aristotle
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20170114/301d043d/attachment.sig>
More information about the ffmpeg-devel
mailing list