diff --git a/common/recorder.c b/common/recorder.c index 1621e8a602..0cbc81d51c 100644 --- a/common/recorder.c +++ b/common/recorder.c @@ -23,6 +23,7 @@ #include "common/common.h" #include "common/global.h" #include "common/msg.h" +#include "demux/demux.h" #include "demux/packet.h" #include "demux/stheader.h" @@ -119,7 +120,9 @@ static int add_stream(struct mp_recorder *priv, struct sh_stream *sh) struct mp_recorder *mp_recorder_create(struct mpv_global *global, const char *target_file, struct sh_stream **streams, - int num_streams) + int num_streams, + struct demux_attachment **attachments, + int num_attachments) { struct mp_recorder *priv = talloc_zero(NULL, struct mp_recorder); @@ -153,6 +156,35 @@ struct mp_recorder *mp_recorder_create(struct mpv_global *global, } } + if (!strcmp(priv->mux->oformat->name, "matroska")) { + // Only attach attachments (fonts) to matroska - mp4, nut, mpegts don't + // like them, and we find that out too late in the muxing process. + AVStream *a_stream = NULL; + for (int i = 0; i < num_attachments; ++i) { + a_stream = avformat_new_stream(priv->mux, NULL); + if (!a_stream) { + MP_ERR(priv, "Can't mux one of the attachments.\n"); + goto error; + } + struct demux_attachment *attachment = attachments[i]; + + a_stream->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; + + a_stream->codecpar->extradata = av_mallocz( + attachment->data_size + AV_INPUT_BUFFER_PADDING_SIZE + ); + if (!a_stream->codecpar->extradata) { + goto error; + } + memcpy(a_stream->codecpar->extradata, + attachment->data, attachment->data_size); + a_stream->codecpar->extradata_size = attachment->data_size; + + av_dict_set(&a_stream->metadata, "filename", attachment->name, 0); + av_dict_set(&a_stream->metadata, "mimetype", attachment->type, 0); + } + } + // Not sure how to write this in a "standard" way. It appears only mkv // and mp4 support this directly. char version[200]; diff --git a/common/recorder.h b/common/recorder.h index c0b1e36495..e86d978067 100644 --- a/common/recorder.h +++ b/common/recorder.h @@ -5,12 +5,15 @@ struct mp_recorder; struct mpv_global; struct demux_packet; struct sh_stream; +struct demux_attachment; struct mp_recorder_sink; struct mp_recorder *mp_recorder_create(struct mpv_global *global, const char *target_file, struct sh_stream **streams, - int num_streams); + int num_streams, + struct demux_attachment **demux_attachments, + int num_attachments); void mp_recorder_destroy(struct mp_recorder *r); void mp_recorder_mark_discontinuity(struct mp_recorder *r); diff --git a/demux/demux.c b/demux/demux.c index 980f4a35d6..650078d068 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -1944,9 +1944,18 @@ static struct mp_recorder *recorder_create(struct demux_internal *in, if (stream->ds->selected) MP_TARRAY_APPEND(NULL, streams, num_streams, stream); } + + struct demuxer *demuxer = in->d_thread; + struct demux_attachment **attachments = talloc_array(NULL, struct demux_attachment*, demuxer->num_attachments); + for (int n = 0; n < demuxer->num_attachments; n++) { + attachments[n] = &demuxer->attachments[n]; + } + struct mp_recorder *res = mp_recorder_create(in->d_thread->global, dst, - streams, num_streams); + streams, num_streams, + attachments, demuxer->num_attachments); talloc_free(streams); + talloc_free(attachments); return res; } diff --git a/player/loadfile.c b/player/loadfile.c index 6032cf6193..e992df694f 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -1959,11 +1959,18 @@ void open_recorder(struct MPContext *mpctx, bool on_init) MP_TARRAY_APPEND(NULL, streams, num_streams, track->stream); } + struct demux_attachment **attachments = talloc_array(NULL, struct demux_attachment*, mpctx->demuxer->num_attachments); + for (int n = 0; n < mpctx->demuxer->num_attachments; n++) { + attachments[n] = &mpctx->demuxer->attachments[n]; + } + mpctx->recorder = mp_recorder_create(mpctx->global, mpctx->opts->record_file, - streams, num_streams); + streams, num_streams, + attachments, mpctx->demuxer->num_attachments); if (!mpctx->recorder) { talloc_free(streams); + talloc_free(attachments); close_recorder_and_error(mpctx); return; } @@ -1987,5 +1994,6 @@ void open_recorder(struct MPContext *mpctx, bool on_init) } talloc_free(streams); + talloc_free(attachments); }