avformat: Add and use helper function to add attachment streams

All instances of adding attached pictures to a stream or adding
a stream and an attached packet to said stream have several things
in common like setting the index and flags of the packet, setting
the stream disposition etc. This commit therefore factors this out.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
Andreas Rheinhardt 2021-03-29 07:58:56 +02:00
parent b7b73e83e3
commit 39ecb63d0f
8 changed files with 66 additions and 77 deletions

View File

@ -79,20 +79,12 @@ static int ape_tag_read_field(AVFormatContext *s)
av_dict_set(&st->metadata, key, filename, 0); av_dict_set(&st->metadata, key, filename, 0);
if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) { if ((id = ff_guess_image2_codec(filename)) != AV_CODEC_ID_NONE) {
int ret; int ret = ff_add_attached_pic(s, st, s->pb, NULL, size);
ret = av_get_packet(s->pb, &st->attached_pic, size);
if (ret < 0) { if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Error reading cover art.\n"); av_log(s, AV_LOG_ERROR, "Error reading cover art.\n");
return ret; return ret;
} }
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = id; st->codecpar->codec_id = id;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
} else { } else {
if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0) if ((ret = ff_get_extradata(s, st->codecpar, s->pb, size)) < 0)
return ret; return ret;

View File

@ -160,20 +160,11 @@ int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size, int tr
if (AV_RB64(data->data) == PNGSIG) if (AV_RB64(data->data) == PNGSIG)
id = AV_CODEC_ID_PNG; id = AV_CODEC_ID_PNG;
st = avformat_new_stream(s, NULL); ret = ff_add_attached_pic(s, NULL, NULL, &data, 0);
if (!st) { if (ret < 0)
RETURN_ERROR(AVERROR(ENOMEM)); RETURN_ERROR(ret);
}
av_packet_unref(&st->attached_pic); st = s->streams[s->nb_streams - 1];
st->attached_pic.buf = data;
st->attached_pic.data = data->data;
st->attached_pic.size = len;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = id; st->codecpar->codec_id = id;
st->codecpar->width = width; st->codecpar->width = width;
st->codecpar->height = height; st->codecpar->height = height;

View File

@ -1142,34 +1142,25 @@ int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
for (cur = extra_meta; cur; cur = cur->next) { for (cur = extra_meta; cur; cur = cur->next) {
ID3v2ExtraMetaAPIC *apic; ID3v2ExtraMetaAPIC *apic;
AVStream *st; AVStream *st;
int ret;
if (strcmp(cur->tag, "APIC")) if (strcmp(cur->tag, "APIC"))
continue; continue;
apic = &cur->data.apic; apic = &cur->data.apic;
if (!(st = avformat_new_stream(s, NULL))) ret = ff_add_attached_pic(s, NULL, NULL, &apic->buf, 0);
return AVERROR(ENOMEM); if (ret < 0)
return ret;
st->disposition |= AV_DISPOSITION_ATTACHED_PIC; st = s->streams[s->nb_streams - 1];
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = apic->id; st->codecpar->codec_id = apic->id;
if (AV_RB64(apic->buf->data) == PNGSIG) if (AV_RB64(st->attached_pic.data) == PNGSIG)
st->codecpar->codec_id = AV_CODEC_ID_PNG; st->codecpar->codec_id = AV_CODEC_ID_PNG;
if (apic->description[0]) if (apic->description[0])
av_dict_set(&st->metadata, "title", apic->description, 0); av_dict_set(&st->metadata, "title", apic->description, 0);
av_dict_set(&st->metadata, "comment", apic->type, 0); av_dict_set(&st->metadata, "comment", apic->type, 0);
av_packet_unref(&st->attached_pic);
st->attached_pic.buf = apic->buf;
st->attached_pic.data = apic->buf->data;
st->attached_pic.size = apic->buf->size - AV_INPUT_BUFFER_PADDING_SIZE;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
apic->buf = NULL;
} }
return 0; return 0;

View File

@ -669,6 +669,19 @@ int ff_framehash_write_header(AVFormatContext *s);
*/ */
int ff_read_packet(AVFormatContext *s, AVPacket *pkt); int ff_read_packet(AVFormatContext *s, AVPacket *pkt);
/**
* Add an attached pic to an AVStream.
*
* @param st if set, the stream to add the attached pic to;
* if unset, a new stream will be added to s.
* @param pb AVIOContext to read data from if buf is unset.
* @param buf if set, it contains the data and size information to be used
* for the attached pic; if unset, data is read from pb.
* @param size the size of the data to read if buf is unset.
*/
int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb,
AVBufferRef **buf, int size);
/** /**
* Interleave an AVPacket per dts so it can be muxed. * Interleave an AVPacket per dts so it can be muxed.
* *

View File

@ -3007,18 +3007,9 @@ static int matroska_read_header(AVFormatContext *s)
attachments[j].stream = st; attachments[j].stream = st;
if (st->codecpar->codec_id != AV_CODEC_ID_NONE) { if (st->codecpar->codec_id != AV_CODEC_ID_NONE) {
AVPacket *pkt = &st->attached_pic; res = ff_add_attached_pic(s, st, NULL, &attachments[j].bin.buf, 0);
if (res < 0)
st->disposition |= AV_DISPOSITION_ATTACHED_PIC; goto fail;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
av_packet_unref(pkt);
pkt->buf = attachments[j].bin.buf;
attachments[j].bin.buf = NULL;
pkt->data = attachments[j].bin.data;
pkt->size = attachments[j].bin.size;
pkt->stream_index = st->index;
pkt->flags |= AV_PKT_FLAG_KEY;
} else { } else {
st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT;
if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size)) if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size))

View File

@ -196,17 +196,16 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
return 0; return 0;
} }
st = avformat_new_stream(c->fc, NULL);
if (!st)
return AVERROR(ENOMEM);
sc = av_mallocz(sizeof(*sc)); sc = av_mallocz(sizeof(*sc));
if (!sc) if (!sc)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
st->priv_data = sc; ret = ff_add_attached_pic(c->fc, NULL, pb, NULL, len);
if (ret < 0) {
ret = av_get_packet(pb, &st->attached_pic, len); av_free(sc);
if (ret < 0)
return ret; return ret;
}
st = c->fc->streams[c->fc->nb_streams - 1];
st->priv_data = sc;
if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) { if (st->attached_pic.size >= 8 && id != AV_CODEC_ID_BMP) {
if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) { if (AV_RB64(st->attached_pic.data) == 0x89504e470d0a1a0a) {
@ -215,13 +214,6 @@ static int mov_read_covr(MOVContext *c, AVIOContext *pb, int type, int len)
id = AV_CODEC_ID_MJPEG; id = AV_CODEC_ID_MJPEG;
} }
} }
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = id; st->codecpar->codec_id = id;
return 0; return 0;
@ -7233,11 +7225,8 @@ static void mov_read_chapters(AVFormatContext *s)
goto finish; goto finish;
} }
if (av_get_packet(sc->pb, &st->attached_pic, sample->size) < 0) if (ff_add_attached_pic(s, st, sc->pb, NULL, sample->size) < 0)
goto finish; goto finish;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
} }
} else { } else {
st->codecpar->codec_type = AVMEDIA_TYPE_DATA; st->codecpar->codec_type = AVMEDIA_TYPE_DATA;

View File

@ -474,6 +474,36 @@ int avformat_queue_attached_pictures(AVFormatContext *s)
return 0; return 0;
} }
int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb,
AVBufferRef **buf, int size)
{
AVPacket *pkt;
int ret;
if (!st && !(st = avformat_new_stream(s, NULL)))
return AVERROR(ENOMEM);
pkt = &st->attached_pic;
if (buf) {
av_assert1(*buf);
av_packet_unref(pkt);
pkt->buf = *buf;
pkt->data = (*buf)->data;
pkt->size = (*buf)->size - AV_INPUT_BUFFER_PADDING_SIZE;
*buf = NULL;
} else {
ret = av_get_packet(pb, pkt, size);
if (ret < 0)
return ret;
}
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
pkt->stream_index = st->index;
pkt->flags |= AV_PKT_FLAG_KEY;
return 0;
}
static int update_stream_avctx(AVFormatContext *s) static int update_stream_avctx(AVFormatContext *s)
{ {
int i, ret; int i, ret;

View File

@ -434,7 +434,6 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
char description[1024]; char description[1024];
unsigned int filesize; unsigned int filesize;
AVStream *st; AVStream *st;
int ret;
int64_t pos = avio_tell(pb); int64_t pos = avio_tell(pb);
avio_get_str16le(pb, INT_MAX, mime, sizeof(mime)); avio_get_str16le(pb, INT_MAX, mime, sizeof(mime));
@ -447,19 +446,12 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length)
if (!filesize) if (!filesize)
goto done; goto done;
st = avformat_new_stream(s, NULL); if (ff_add_attached_pic(s, NULL, pb, NULL, filesize) < 0)
if (!st)
goto done; goto done;
st = s->streams[s->nb_streams - 1];
av_dict_set(&st->metadata, "title", description, 0); av_dict_set(&st->metadata, "title", description, 0);
st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
st->codecpar->codec_id = AV_CODEC_ID_MJPEG; st->codecpar->codec_id = AV_CODEC_ID_MJPEG;
st->id = -1; st->id = -1;
ret = av_get_packet(pb, &st->attached_pic, filesize);
if (ret < 0)
goto done;
st->attached_pic.stream_index = st->index;
st->attached_pic.flags |= AV_PKT_FLAG_KEY;
st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
done: done:
avio_seek(pb, pos + length, SEEK_SET); avio_seek(pb, pos + length, SEEK_SET);
} }