summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-02-05 21:52:07 +0100
committerwm4 <wm4@nowhere>2015-02-05 21:52:07 +0100
commit1f2a370a03fff9f1156f3cafa2255c27b61cc35d (patch)
tree8fa504a5201f66cf2567217d15f431e191195c14 /demux
parentf8d7756a14a8073f24c31b3854b7e64784cbb002 (diff)
downloadmpv-1f2a370a03fff9f1156f3cafa2255c27b61cc35d.tar.bz2
mpv-1f2a370a03fff9f1156f3cafa2255c27b61cc35d.tar.xz
demux_mkv: refactor packet parsing
Makes it somewhat more uniform, and breaks up the awfully deep nesting. This implicitly changes multiple small details, rather than only moving code around. In particular, this computes the packet fields first and parses them afterwards, which is needed for the next commit.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux_mkv.c185
-rw-r--r--demux/packet.c14
-rw-r--r--demux/packet.h2
3 files changed, 115 insertions, 86 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 6382126f0a..a476ee0f6e 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -2242,58 +2242,86 @@ fail:
return -1;
}
-static bool mkv_parse_packet(mkv_track_t *track, bstr *raw, bstr *out)
+static void mkv_parse_and_add_packet(demuxer_t *demuxer, mkv_track_t *track,
+ struct demux_packet *dp)
{
+ struct sh_stream *stream = track->stream;
+
+ if (track->realmedia) {
+ bstr block = {dp->buffer, dp->len};
+ if (stream->type == STREAM_VIDEO)
+ handle_realvideo(demuxer, track, block, dp->keyframe);
+ if (stream->type == STREAM_AUDIO)
+ handle_realaudio(demuxer, track, block, dp->keyframe);
+ talloc_free(dp);
+ return;
+ }
+
if (track->a_formattag == MP_FOURCC('W', 'V', 'P', 'K')) {
- int size = raw->len;
+ int size = dp->len;
uint8_t *parsed;
- if (libav_parse_wavpack(track, raw->start, &parsed, &size) >= 0) {
- out->start = parsed;
- out->len = size;
- *raw = (bstr){0};
- return true;
- }
- } else if (track->codec_id && strcmp(track->codec_id, MKV_V_PRORES) == 0) {
- size_t newlen = raw->len + 8;
- char *data = talloc_size(track->parser_tmp, newlen);
- AV_WB32(data + 0, newlen);
- AV_WB32(data + 4, MKBETAG('i', 'c', 'p', 'f'));
- memcpy(data + 8, raw->start, raw->len);
- out->start = data;
- out->len = newlen;
- *raw = (bstr){0};
- return true;
- } else if (track->parse) {
- if (!track->av_parser) {
- int id = mp_codec_to_av_codec_id(track->stream->codec);
- const AVCodec *codec = avcodec_find_decoder(id);
- track->av_parser = av_parser_init(id);
- if (codec)
- track->av_parser_codec = avcodec_alloc_context3(codec);
- }
- if (track->av_parser && track->av_parser_codec) {
- while (raw->len) {
- uint8_t *data = NULL;
- int size = 0;
- int len = av_parser_parse2(track->av_parser, track->av_parser_codec,
- &data, &size, raw->start, raw->len,
- AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
- if (len < 0 || len > 0x10000000)
- return false;
- *raw = bstr_cut(*raw, len);
- if (size) {
- out->start = data;
- out->len = size;
- return true;
- }
+ if (libav_parse_wavpack(track, dp->buffer, &parsed, &size) >= 0) {
+ struct demux_packet *new = new_demux_packet_from(parsed, size);
+ if (new) {
+ demux_packet_copy_attribs(new, dp);
+ talloc_free(dp);
+ demux_add_packet(stream, new);
+ return;
}
- return false;
}
}
- // No parsing
- *out = *raw;
- *raw = (bstr){0};
- return true;
+
+ if (track->codec_id && strcmp(track->codec_id, MKV_V_PRORES) == 0) {
+ size_t newlen = dp->len + 8;
+ struct demux_packet *new = new_demux_packet(newlen);
+ if (new) {
+ AV_WB32(new->buffer + 0, newlen);
+ AV_WB32(new->buffer + 4, MKBETAG('i', 'c', 'p', 'f'));
+ memcpy(new->buffer + 8, dp->buffer, dp->len);
+ demux_packet_copy_attribs(new, dp);
+ talloc_free(dp);
+ demux_add_packet(stream, new);
+ return;
+ }
+ }
+
+ if (track->parse && !track->av_parser) {
+ int id = mp_codec_to_av_codec_id(track->stream->codec);
+ const AVCodec *codec = avcodec_find_decoder(id);
+ track->av_parser = av_parser_init(id);
+ if (codec)
+ track->av_parser_codec = avcodec_alloc_context3(codec);
+ }
+
+ if (!track->parse || !track->av_parser || !track->av_parser_codec) {
+ demux_add_packet(stream, dp);
+ return;
+ }
+
+ while (dp->len) {
+ uint8_t *data = NULL;
+ int size = 0;
+ int len = av_parser_parse2(track->av_parser, track->av_parser_codec,
+ &data, &size, dp->buffer, dp->len,
+ AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
+ if (len < 0 || len > dp->len)
+ break;
+ dp->buffer += len;
+ dp->len -= len;
+ if (size) {
+ struct demux_packet *new = new_demux_packet_from(data, size);
+ if (!new)
+ break;
+ demux_packet_copy_attribs(new, dp);
+ demux_add_packet(stream, new);
+ }
+ }
+
+ if (dp->len) {
+ demux_add_packet(stream, dp);
+ } else {
+ talloc_free(dp);
+ }
}
struct block_info {
@@ -2431,46 +2459,37 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
mkv_d->last_pts = current_pts;
mkv_d->last_filepos = block_info->filepos;
- int p = 0;
for (int i = 0; i < laces; i++) {
bstr block = bstr_splice(data, 0, lace_size[i]);
- if (stream->type == STREAM_VIDEO && track->realmedia)
- handle_realvideo(demuxer, track, block, keyframe);
- else if (stream->type == STREAM_AUDIO && track->realmedia)
- handle_realaudio(demuxer, track, block, keyframe);
- else {
- bstr raw = demux_mkv_decode(demuxer->log, track, block, 1);
- bstr buffer;
- while (raw.start && mkv_parse_packet(track, &raw, &buffer)) {
- demux_packet_t *dp =
- new_demux_packet_from(buffer.start, buffer.len);
- if (!dp)
- break;
- dp->keyframe = keyframe;
- dp->pos = mkv_d->last_filepos;
- /* If default_duration is 0, assume no pts value is known
- * for packets after the first one (rather than all pts
- * values being the same). Also, don't use it for extra
- * packets resulting from parsing. */
- if (p == 0 || (p == i && track->default_duration))
- dp->pts = mkv_d->last_pts + p * track->default_duration;
- if (track->ms_compat)
- 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++;
- }
- talloc_free_children(track->parser_tmp);
- }
data = bstr_cut(data, lace_size[i]);
+
+ block = demux_mkv_decode(demuxer->log, track, block, 1);
+
+ demux_packet_t *dp = new_demux_packet_from(block.start, block.len);
+ if (!dp)
+ break;
+ dp->keyframe = keyframe;
+ dp->pos = mkv_d->last_filepos;
+ /* If default_duration is 0, assume no pts value is known
+ * for packets after the first one (rather than all pts
+ * values being the same). Also, don't use it for extra
+ * packets resulting from parsing. */
+ if (i == 0 || track->default_duration)
+ dp->pts = mkv_d->last_pts + i * track->default_duration;
+ if (track->ms_compat)
+ MPSWAP(double, dp->pts, dp->dts);
+ if (i == 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;
+ }
+
+ mkv_parse_and_add_packet(demuxer, track, dp);
+ talloc_free_children(track->parser_tmp);
}
if (stream->type == STREAM_VIDEO) {
diff --git a/demux/packet.c b/demux/packet.c
index 1b2d985976..22b111b0ce 100644
--- a/demux/packet.c
+++ b/demux/packet.c
@@ -100,6 +100,16 @@ void free_demux_packet(struct demux_packet *dp)
talloc_free(dp);
}
+void demux_packet_copy_attribs(struct demux_packet *dst, struct demux_packet *src)
+{
+ dst->pts = src->pts;
+ dst->dts = src->dts;
+ dst->duration = src->duration;
+ dst->pos = src->pos;
+ dst->keyframe = src->keyframe;
+ dst->stream = src->stream;
+}
+
struct demux_packet *demux_copy_packet(struct demux_packet *dp)
{
struct demux_packet *new = NULL;
@@ -111,9 +121,7 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp)
}
if (!new)
return NULL;
- new->pts = dp->pts;
- new->dts = dp->dts;
- new->duration = dp->duration;
+ demux_packet_copy_attribs(new, dp);
return new;
}
diff --git a/demux/packet.h b/demux/packet.h
index 4bd724aa93..213ee025cb 100644
--- a/demux/packet.h
+++ b/demux/packet.h
@@ -44,6 +44,8 @@ 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);
+void demux_packet_copy_attribs(struct demux_packet *dst, struct demux_packet *src);
+
int demux_packet_set_padding(struct demux_packet *dp, int start, int end);
#endif /* MPLAYER_DEMUX_PACKET_H */