diff options
author | wm4 <wm4@nowhere> | 2014-11-03 20:00:34 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-11-03 20:20:28 +0100 |
commit | 4e87ac823108a670a1a0c5f67ab9bcd6980bac33 (patch) | |
tree | 4e71fa69834ce2e7886f3870abc3b8766d1605c3 /demux | |
parent | 93e1db0bff5fc48dffeb2dc94801436bdb459cd3 (diff) | |
download | mpv-4e87ac823108a670a1a0c5f67ab9bcd6980bac33.tar.bz2 mpv-4e87ac823108a670a1a0c5f67ab9bcd6980bac33.tar.xz |
demux_mkv: implement audio skipping/trimming
This mechanism was introduced for Opus, and allows correct skipping of
"preroll" data, as well as discarding trailing audio if the file's
length isn't a multiple of the audio frame size.
Not sure how to handle seeking. I don't understand the purpose of the
SeekPreRoll element.
This was tested with correctness_trimming_nobeeps.opus, remuxed to mka
with mkvmerge v7.2.0. It seems to be correct, although the reported file
duration is incorrect (maybe a mkvmerge issue).
Diffstat (limited to 'demux')
-rw-r--r-- | demux/demux_mkv.c | 25 | ||||
-rw-r--r-- | demux/packet.c | 16 | ||||
-rw-r--r-- | demux/packet.h | 2 |
3 files changed, 41 insertions, 2 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 72020ce123..55748ad36c 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -112,6 +112,7 @@ typedef struct mkv_track { float a_osfreq; double default_duration; + double codec_delay; int default_track; @@ -182,6 +183,7 @@ typedef struct mkv_demuxer { uint64_t skip_to_timecode; int v_skip_to_keyframe, a_skip_to_keyframe; + int a_skip_preroll; int subtitle_preroll; } mkv_demuxer_t; @@ -626,6 +628,9 @@ static void parse_trackentry(struct demuxer *demuxer, if (entry->n_content_encodings) parse_trackencodings(demuxer, track, &entry->content_encodings); + if (entry->n_codec_delay) + track->codec_delay = entry->codec_delay / 1e9; + mkv_d->tracks[mkv_d->num_tracks++] = track; } @@ -1750,6 +1755,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) mkv_d->tc_scale = 1000000; mkv_d->segment_start = stream_tell(s); mkv_d->segment_end = end_pos; + mkv_d->a_skip_preroll = 1; if (demuxer->params && demuxer->params->matroska_was_valid) *demuxer->params->matroska_was_valid = true; @@ -2258,7 +2264,7 @@ static bool mkv_parse_packet(mkv_track_t *track, bstr *raw, bstr *out) } struct block_info { - uint64_t duration; + uint64_t duration, discardpadding; bool simple, keyframe; uint64_t timecode; mkv_track_t *track; @@ -2358,7 +2364,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) return 0; } - current_pts = tc / 1e9; + current_pts = tc / 1e9 - track->codec_delay; if (track->type == MATROSKA_TRACK_AUDIO) { if (mkv_d->a_skip_to_keyframe) @@ -2418,6 +2424,13 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) MPSWAP(double, dp->pts, dp->dts); if (p == 0) dp->duration = block_duration / 1e9; + if (stream->type == STREAM_AUDIO) { + unsigned int srate = track->a_sfreq; + demux_packet_set_padding(dp, + mkv_d->a_skip_preroll ? track->codec_delay * srate : 0, + block_info->discardpadding / 1e9 * srate); + mkv_d->a_skip_preroll = 0; + } demux_add_packet(stream, dp); p++; } @@ -2456,6 +2469,12 @@ static int read_block_group(demuxer_t *demuxer, int64_t end, block->duration *= mkv_d->tc_scale; break; + case MATROSKA_ID_DISCARDPADDING: + block->discardpadding = ebml_read_uint(s); + if (block->discardpadding == EBML_UINT_INVALID) + goto error; + break; + case MATROSKA_ID_BLOCK: if (read_block(demuxer, end, block) < 0) goto error; @@ -2745,6 +2764,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) mkv_d->v_skip_to_keyframe = st_active[STREAM_VIDEO]; mkv_d->a_skip_to_keyframe = st_active[STREAM_AUDIO]; + mkv_d->a_skip_preroll = mkv_d->a_skip_to_keyframe; if (flags & SEEK_FORWARD) { mkv_d->skip_to_timecode = target_timecode; @@ -2781,6 +2801,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) mkv_d->v_skip_to_keyframe = st_active[STREAM_VIDEO]; mkv_d->a_skip_to_keyframe = st_active[STREAM_AUDIO]; + mkv_d->a_skip_preroll = mkv_d->a_skip_to_keyframe; if (index) { stream_seek(s, index->filepos); diff --git a/demux/packet.c b/demux/packet.c index 959c707732..968427dee5 100644 --- a/demux/packet.c +++ b/demux/packet.c @@ -20,6 +20,7 @@ #include <assert.h> #include <libavcodec/avcodec.h> +#include <libavutil/intreadwrite.h> #include "common/av_common.h" #include "common/common.h" @@ -113,3 +114,18 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp) new->duration = dp->duration; return new; } + +int demux_packet_set_padding(struct demux_packet *dp, int start, int end) +{ + if (!start && !end) + return 0; + if (!dp->avpacket) + return -1; + uint8_t *p = av_packet_new_side_data(dp->avpacket, AV_PKT_DATA_SKIP_SAMPLES, 10); + if (!p) + return -1; + + AV_WL32(p + 0, start); + AV_WL32(p + 4, end); + return 0; +} diff --git a/demux/packet.h b/demux/packet.h index 9c4e560e05..4bd724aa93 100644 --- a/demux/packet.h +++ b/demux/packet.h @@ -44,4 +44,6 @@ void demux_packet_shorten(struct demux_packet *dp, size_t len); void free_demux_packet(struct demux_packet *dp); struct demux_packet *demux_copy_packet(struct demux_packet *dp); +int demux_packet_set_padding(struct demux_packet *dp, int start, int end); + #endif /* MPLAYER_DEMUX_PACKET_H */ |