summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */