Commit 358b58cb authored by Andreas Rheinhardt's avatar Andreas Rheinhardt

avformat/matroskaenc: Remove allocations for Attachments

If there are Attachments to write, the Matroska muxer currently
allocates two objects: An array that contains an entry for each
AttachedFile containing just the stream index of the corresponding
stream and the FileUID used for this AttachedFile; and a structure with
a pointer to said array and a counter for said array. These uids are
generated via code special to Attachments: It uses an AVLFG in the
normal and a sha of the attachment data in the bitexact case. (Said sha
requires an allocation, too.)

But now that an uid is generated for each stream in mkv_init(), there is
no need any more to use special code for generating the FileUIDs of
AttachedFiles: One can simply use the uid already generated for the
corresponding stream. And this makes the whole allocations of the
structures for AttachedFiles as well as the structures itself superfluous.
They have been removed.

In case AVFMT_FLAG_BITEXACT is set, the uids will be different from the
old ones which is the reason why the FATE-test lavf-mkv_attachment
needed to be updated. The old method had the drawback that two
AttachedFiles with the same data would have the same FileUID.
The new one doesn't.

Also notice that the dynamic buffer used to write the Attachments leaks
if an error happens when writing the buffer. By removing the
allocations potential sources of errors have been removed.
Signed-off-by: 's avatarAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
parent 4b18999b
...@@ -49,7 +49,6 @@ ...@@ -49,7 +49,6 @@
#include "libavutil/random_seed.h" #include "libavutil/random_seed.h"
#include "libavutil/rational.h" #include "libavutil/rational.h"
#include "libavutil/samplefmt.h" #include "libavutil/samplefmt.h"
#include "libavutil/sha.h"
#include "libavutil/stereo3d.h" #include "libavutil/stereo3d.h"
#include "libavcodec/xiph.h" #include "libavcodec/xiph.h"
...@@ -103,16 +102,6 @@ typedef struct mkv_track { ...@@ -103,16 +102,6 @@ typedef struct mkv_track {
int64_t ts_offset; int64_t ts_offset;
} mkv_track; } mkv_track;
typedef struct mkv_attachment {
int stream_idx;
uint32_t fileuid;
} mkv_attachment;
typedef struct mkv_attachments {
mkv_attachment *entries;
int num_entries;
} mkv_attachments;
#define MODE_MATROSKAv2 0x01 #define MODE_MATROSKAv2 0x01
#define MODE_WEBM 0x02 #define MODE_WEBM 0x02
...@@ -139,7 +128,6 @@ typedef struct MatroskaMuxContext { ...@@ -139,7 +128,6 @@ typedef struct MatroskaMuxContext {
mkv_seekhead seekhead; mkv_seekhead seekhead;
mkv_cues cues; mkv_cues cues;
mkv_track *tracks; mkv_track *tracks;
mkv_attachments *attachments;
AVPacket cur_audio_pkt; AVPacket cur_audio_pkt;
...@@ -401,10 +389,6 @@ static void mkv_deinit(AVFormatContext *s) ...@@ -401,10 +389,6 @@ static void mkv_deinit(AVFormatContext *s)
ffio_free_dyn_buf(&mkv->tags_bc); ffio_free_dyn_buf(&mkv->tags_bc);
av_freep(&mkv->cues.entries); av_freep(&mkv->cues.entries);
if (mkv->attachments) {
av_freep(&mkv->attachments->entries);
av_freep(&mkv->attachments);
}
av_freep(&mkv->tracks); av_freep(&mkv->tracks);
} }
...@@ -1615,15 +1599,18 @@ static int mkv_write_tags(AVFormatContext *s) ...@@ -1615,15 +1599,18 @@ static int mkv_write_tags(AVFormatContext *s)
} }
if (mkv->have_attachments && mkv->mode != MODE_WEBM) { if (mkv->have_attachments && mkv->mode != MODE_WEBM) {
for (i = 0; i < mkv->attachments->num_entries; i++) { for (i = 0; i < s->nb_streams; i++) {
mkv_attachment *attachment = &mkv->attachments->entries[i]; mkv_track *track = &mkv->tracks[i];
AVStream *st = s->streams[attachment->stream_idx]; AVStream *st = s->streams[i];
if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
continue;
if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID)) if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID))
continue; continue;
ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID, ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_ATTACHUID,
attachment->fileuid, NULL); track->uid, NULL);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
...@@ -1643,18 +1630,11 @@ static int mkv_write_attachments(AVFormatContext *s) ...@@ -1643,18 +1630,11 @@ static int mkv_write_attachments(AVFormatContext *s)
{ {
MatroskaMuxContext *mkv = s->priv_data; MatroskaMuxContext *mkv = s->priv_data;
AVIOContext *dyn_cp = NULL, *pb = s->pb; AVIOContext *dyn_cp = NULL, *pb = s->pb;
AVLFG c;
int i, ret; int i, ret;
if (!mkv->have_attachments) if (!mkv->have_attachments)
return 0; return 0;
mkv->attachments = av_mallocz(sizeof(*mkv->attachments));
if (!mkv->attachments)
return AVERROR(ENOMEM);
av_lfg_init(&c, av_get_random_seed());
mkv_add_seekhead_entry(mkv, MATROSKA_ID_ATTACHMENTS, avio_tell(pb)); mkv_add_seekhead_entry(mkv, MATROSKA_ID_ATTACHMENTS, avio_tell(pb));
ret = start_ebml_master_crc32(&dyn_cp, mkv); ret = start_ebml_master_crc32(&dyn_cp, mkv);
...@@ -1662,20 +1642,14 @@ static int mkv_write_attachments(AVFormatContext *s) ...@@ -1662,20 +1642,14 @@ static int mkv_write_attachments(AVFormatContext *s)
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i]; AVStream *st = s->streams[i];
mkv_track *track = &mkv->tracks[i];
ebml_master attached_file; ebml_master attached_file;
mkv_attachment *attachment = mkv->attachments->entries;
AVDictionaryEntry *t; AVDictionaryEntry *t;
const char *mimetype = NULL; const char *mimetype = NULL;
uint32_t fileuid;
if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT) if (st->codecpar->codec_type != AVMEDIA_TYPE_ATTACHMENT)
continue; continue;
attachment = av_realloc_array(attachment, mkv->attachments->num_entries + 1, sizeof(mkv_attachment));
if (!attachment)
return AVERROR(ENOMEM);
mkv->attachments->entries = attachment;
attached_file = start_ebml_master(dyn_cp, MATROSKA_ID_ATTACHEDFILE, 0); attached_file = start_ebml_master(dyn_cp, MATROSKA_ID_ATTACHEDFILE, 0);
if (t = av_dict_get(st->metadata, "title", NULL, 0)) if (t = av_dict_get(st->metadata, "title", NULL, 0))
...@@ -1706,29 +1680,10 @@ static int mkv_write_attachments(AVFormatContext *s) ...@@ -1706,29 +1680,10 @@ static int mkv_write_attachments(AVFormatContext *s)
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (s->flags & AVFMT_FLAG_BITEXACT) {
struct AVSHA *sha = av_sha_alloc();
uint8_t digest[20];
if (!sha)
return AVERROR(ENOMEM);
av_sha_init(sha, 160);
av_sha_update(sha, st->codecpar->extradata, st->codecpar->extradata_size);
av_sha_final(sha, digest);
av_free(sha);
fileuid = AV_RL32(digest);
} else {
fileuid = av_lfg_get(&c);
}
av_log(s, AV_LOG_VERBOSE, "Using %.8"PRIx32" for attachment %d\n",
fileuid, mkv->attachments->num_entries);
put_ebml_string(dyn_cp, MATROSKA_ID_FILEMIMETYPE, mimetype); put_ebml_string(dyn_cp, MATROSKA_ID_FILEMIMETYPE, mimetype);
put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size); put_ebml_binary(dyn_cp, MATROSKA_ID_FILEDATA, st->codecpar->extradata, st->codecpar->extradata_size);
put_ebml_uint(dyn_cp, MATROSKA_ID_FILEUID, fileuid); put_ebml_uint(dyn_cp, MATROSKA_ID_FILEUID, track->uid);
end_ebml_master(dyn_cp, attached_file); end_ebml_master(dyn_cp, attached_file);
mkv->attachments->entries[mkv->attachments->num_entries].stream_idx = i;
mkv->attachments->entries[mkv->attachments->num_entries++].fileuid = fileuid;
} }
end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0); end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0);
......
c339e42793d2a3cb1b8e99fc7a60de31 *tests/data/lavf/lavf.mkv_attachment 6f68dccaaaf875a0671f47e5b21c8cca *tests/data/lavf/lavf.mkv_attachment
472569 tests/data/lavf/lavf.mkv_attachment 472566 tests/data/lavf/lavf.mkv_attachment
tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68 tests/data/lavf/lavf.mkv_attachment CRC=0xec6c3c68
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment