1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-08-10 06:10:52 +02:00

avformat/matroskadec: use refcounted buffers in EbmlBin

Data in EbmlBin objects is never changed after being read from the
input file (save for two specific cases with encoded CodePrivate), so
using AVBufferRef we can prevent unnecessary copy of data by instead
creating new references to said constant data.

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2018-04-04 14:12:54 -03:00
parent 647fd4b829
commit a61886650b

View File

@@ -104,6 +104,7 @@ typedef struct EbmlList {
typedef struct EbmlBin { typedef struct EbmlBin {
int size; int size;
AVBufferRef *buf;
uint8_t *data; uint8_t *data;
int64_t pos; int64_t pos;
} EbmlBin; } EbmlBin;
@@ -962,14 +963,19 @@ static int ebml_read_ascii(AVIOContext *pb, int size, char **str)
*/ */
static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin) static int ebml_read_binary(AVIOContext *pb, int length, EbmlBin *bin)
{ {
av_fast_padded_malloc(&bin->data, &bin->size, length); int ret;
if (!bin->data)
return AVERROR(ENOMEM);
ret = av_buffer_realloc(&bin->buf, length + AV_INPUT_BUFFER_PADDING_SIZE);
if (ret < 0)
return ret;
memset(bin->buf->data + length, 0, AV_INPUT_BUFFER_PADDING_SIZE);
bin->data = bin->buf->data;
bin->size = length; bin->size = length;
bin->pos = avio_tell(pb); bin->pos = avio_tell(pb);
if (avio_read(pb, bin->data, length) != length) { if (avio_read(pb, bin->data, length) != length) {
av_freep(&bin->data); av_buffer_unref(&bin->buf);
bin->data = NULL;
bin->size = 0; bin->size = 0;
return AVERROR(EIO); return AVERROR(EIO);
} }
@@ -1252,7 +1258,7 @@ static void ebml_free(EbmlSyntax *syntax, void *data)
av_freep(data_off); av_freep(data_off);
break; break;
case EBML_BIN: case EBML_BIN:
av_freep(&((EbmlBin *) data_off)->data); av_buffer_unref(&((EbmlBin *) data_off)->buf);
break; break;
case EBML_LEVEL1: case EBML_LEVEL1:
case EBML_NEST: case EBML_NEST:
@@ -2036,12 +2042,13 @@ static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *
* by expanding/shifting the data by 4 bytes and storing the data * by expanding/shifting the data by 4 bytes and storing the data
* size at the start. */ * size at the start. */
if (ff_codec_get_id(codec_tags, AV_RL32(track->codec_priv.data))) { if (ff_codec_get_id(codec_tags, AV_RL32(track->codec_priv.data))) {
uint8_t *p = av_realloc(track->codec_priv.data, int ret = av_buffer_realloc(&track->codec_priv.buf,
track->codec_priv.size + 4); track->codec_priv.size + 4 + AV_INPUT_BUFFER_PADDING_SIZE);
if (!p) if (ret < 0)
return AVERROR(ENOMEM); return ret;
memmove(p + 4, p, track->codec_priv.size);
track->codec_priv.data = p; track->codec_priv.data = track->codec_priv.buf->data;
memmove(track->codec_priv.data + 4, track->codec_priv.data, track->codec_priv.size);
track->codec_priv.size += 4; track->codec_priv.size += 4;
AV_WB32(track->codec_priv.data, track->codec_priv.size); AV_WB32(track->codec_priv.data, track->codec_priv.size);
} }
@@ -2162,8 +2169,19 @@ static int matroska_parse_tracks(AVFormatContext *s)
"Failed to decode codec private data\n"); "Failed to decode codec private data\n");
} }
if (codec_priv != track->codec_priv.data) if (codec_priv != track->codec_priv.data) {
av_free(codec_priv); av_buffer_unref(&track->codec_priv.buf);
if (track->codec_priv.data) {
track->codec_priv.buf = av_buffer_create(track->codec_priv.data,
track->codec_priv.size + AV_INPUT_BUFFER_PADDING_SIZE,
NULL, NULL, 0);
if (!track->codec_priv.buf) {
av_freep(&track->codec_priv.data);
track->codec_priv.size = 0;
return AVERROR(ENOMEM);
}
}
}
} }
} }