recorder: add support for attachments (fonts)

Though, only when the output format is matroska, to avoid muxing errors.
This is quite useful when the input has ASS subtitles, as they tend to
rely on embedded fonts.
This commit is contained in:
TheAMM 2021-05-29 01:28:15 +03:00 committed by Jan Ekström
parent f9527497c6
commit 4d3df1c842
4 changed files with 56 additions and 4 deletions

View File

@ -23,6 +23,7 @@
#include "common/common.h" #include "common/common.h"
#include "common/global.h" #include "common/global.h"
#include "common/msg.h" #include "common/msg.h"
#include "demux/demux.h"
#include "demux/packet.h" #include "demux/packet.h"
#include "demux/stheader.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, struct mp_recorder *mp_recorder_create(struct mpv_global *global,
const char *target_file, const char *target_file,
struct sh_stream **streams, 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); 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 // Not sure how to write this in a "standard" way. It appears only mkv
// and mp4 support this directly. // and mp4 support this directly.
char version[200]; char version[200];

View File

@ -5,12 +5,15 @@ struct mp_recorder;
struct mpv_global; struct mpv_global;
struct demux_packet; struct demux_packet;
struct sh_stream; struct sh_stream;
struct demux_attachment;
struct mp_recorder_sink; struct mp_recorder_sink;
struct mp_recorder *mp_recorder_create(struct mpv_global *global, struct mp_recorder *mp_recorder_create(struct mpv_global *global,
const char *target_file, const char *target_file,
struct sh_stream **streams, 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_destroy(struct mp_recorder *r);
void mp_recorder_mark_discontinuity(struct mp_recorder *r); void mp_recorder_mark_discontinuity(struct mp_recorder *r);

View File

@ -1944,9 +1944,18 @@ static struct mp_recorder *recorder_create(struct demux_internal *in,
if (stream->ds->selected) if (stream->ds->selected)
MP_TARRAY_APPEND(NULL, streams, num_streams, stream); 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, 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(streams);
talloc_free(attachments);
return res; return res;
} }

View File

@ -1959,11 +1959,18 @@ void open_recorder(struct MPContext *mpctx, bool on_init)
MP_TARRAY_APPEND(NULL, streams, num_streams, track->stream); 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, 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) { if (!mpctx->recorder) {
talloc_free(streams); talloc_free(streams);
talloc_free(attachments);
close_recorder_and_error(mpctx); close_recorder_and_error(mpctx);
return; return;
} }
@ -1987,5 +1994,6 @@ void open_recorder(struct MPContext *mpctx, bool on_init)
} }
talloc_free(streams); talloc_free(streams);
talloc_free(attachments);
} }