2 * Raw FLAC picture parser
3 * Copyright (c) 2001 Fabrice Bellard
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "libavutil/avassert.h"
24 #include "flac_picture.h"
28 int ff_flac_parse_picture(AVFormatContext
*s
, uint8_t *buf
, int buf_size
)
30 const CodecMime
*mime
= ff_id3v2_mime_tags
;
31 enum AVCodecID id
= AV_CODEC_ID_NONE
;
32 AVBufferRef
*data
= NULL
;
33 uint8_t mimetype
[64], *desc
= NULL
;
34 AVIOContext
*pb
= NULL
;
36 int type
, width
, height
;
39 pb
= avio_alloc_context(buf
, buf_size
, 0, NULL
, NULL
, NULL
, NULL
);
41 return AVERROR(ENOMEM
);
43 /* read the picture type */
45 if (type
>= FF_ARRAY_ELEMS(ff_id3v2_picture_types
) || type
< 0) {
46 av_log(s
, AV_LOG_ERROR
, "Invalid picture type: %d.\n", type
);
47 if (s
->error_recognition
& AV_EF_EXPLODE
) {
48 RETURN_ERROR(AVERROR_INVALIDDATA
);
53 /* picture mimetype */
56 avio_read(pb
, mimetype
, FFMIN(len
, sizeof(mimetype
) - 1)) != len
) {
57 av_log(s
, AV_LOG_ERROR
, "Could not read mimetype from an attached "
59 if (s
->error_recognition
& AV_EF_EXPLODE
)
60 ret
= AVERROR_INVALIDDATA
;
63 av_assert0(len
< sizeof(mimetype
));
66 while (mime
->id
!= AV_CODEC_ID_NONE
) {
67 if (!strncmp(mime
->str
, mimetype
, sizeof(mimetype
))) {
73 if (id
== AV_CODEC_ID_NONE
) {
74 av_log(s
, AV_LOG_ERROR
, "Unknown attached picture mimetype: %s.\n",
76 if (s
->error_recognition
& AV_EF_EXPLODE
)
77 ret
= AVERROR_INVALIDDATA
;
81 /* picture description */
84 if (!(desc
= av_malloc(len
+ 1))) {
85 RETURN_ERROR(AVERROR(ENOMEM
));
88 if (avio_read(pb
, desc
, len
) != len
) {
89 av_log(s
, AV_LOG_ERROR
, "Error reading attached picture description.\n");
90 if (s
->error_recognition
& AV_EF_EXPLODE
)
97 /* picture metadata */
98 width
= avio_rb32(pb
);
99 height
= avio_rb32(pb
);
105 av_log(s
, AV_LOG_ERROR
, "Invalid attached picture size: %d.\n", len
);
106 if (s
->error_recognition
& AV_EF_EXPLODE
)
107 ret
= AVERROR_INVALIDDATA
;
110 if (!(data
= av_buffer_alloc(len
+ FF_INPUT_BUFFER_PADDING_SIZE
))) {
111 RETURN_ERROR(AVERROR(ENOMEM
));
113 memset(data
->data
+ len
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
114 if (avio_read(pb
, data
->data
, len
) != len
) {
115 av_log(s
, AV_LOG_ERROR
, "Error reading attached picture data.\n");
116 if (s
->error_recognition
& AV_EF_EXPLODE
)
121 st
= avformat_new_stream(s
, NULL
);
123 RETURN_ERROR(AVERROR(ENOMEM
));
126 av_init_packet(&st
->attached_pic
);
127 st
->attached_pic
.buf
= data
;
128 st
->attached_pic
.data
= data
->data
;
129 st
->attached_pic
.size
= len
;
130 st
->attached_pic
.stream_index
= st
->index
;
131 st
->attached_pic
.flags
|= AV_PKT_FLAG_KEY
;
133 st
->disposition
|= AV_DISPOSITION_ATTACHED_PIC
;
134 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
135 st
->codec
->codec_id
= id
;
136 st
->codec
->width
= width
;
137 st
->codec
->height
= height
;
138 av_dict_set(&st
->metadata
, "comment", ff_id3v2_picture_types
[type
], 0);
140 av_dict_set(&st
->metadata
, "title", desc
, AV_DICT_DONT_STRDUP_VAL
);
147 av_buffer_unref(&data
);