• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * raw FLAC muxer
3  * Copyright (c) 2006-2009 Justin Ruggles
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 #include "libavutil/avstring.h"
23 #include "libavutil/channel_layout.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/pixdesc.h"
26 #include "libavcodec/flac.h"
27 #include "libavcodec/packet_internal.h"
28 #include "avformat.h"
29 #include "avio_internal.h"
30 #include "flacenc.h"
31 #include "id3v2.h"
32 #include "internal.h"
33 #include "version.h"
34 #include "vorbiscomment.h"
35 
36 
37 typedef struct FlacMuxerContext {
38     const AVClass *class;
39     int write_header;
40 
41     int audio_stream_idx;
42     int waiting_pics;
43     /* audio packets are queued here until we get all the attached pictures */
44     PacketList queue;
45 
46     /* updated streaminfo sent by the encoder at the end */
47     uint8_t streaminfo[FLAC_STREAMINFO_SIZE];
48     int updated_streaminfo;
49 
50     unsigned attached_types;
51 } FlacMuxerContext;
52 
flac_write_block_padding(AVIOContext * pb,unsigned int n_padding_bytes,int last_block)53 static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes,
54                                     int last_block)
55 {
56     avio_w8(pb, last_block ? 0x81 : 0x01);
57     avio_wb24(pb, n_padding_bytes);
58     ffio_fill(pb, 0, n_padding_bytes);
59     return 0;
60 }
61 
flac_write_block_comment(AVIOContext * pb,AVDictionary ** m,int last_block,int bitexact)62 static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
63                                     int last_block, int bitexact)
64 {
65     const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
66     int64_t len;
67 
68     ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
69 
70     len = ff_vorbiscomment_length(*m, vendor, NULL, 0);
71     if (len >= ((1<<24) - 4))
72         return AVERROR(EINVAL);
73 
74     avio_w8(pb, last_block ? 0x84 : 0x04);
75     avio_wb24(pb, len);
76     ff_vorbiscomment_write(pb, *m, vendor, NULL, 0);
77 
78     return 0;
79 }
80 
flac_write_picture(struct AVFormatContext * s,AVPacket * pkt)81 static int flac_write_picture(struct AVFormatContext *s, AVPacket *pkt)
82 {
83     FlacMuxerContext *c = s->priv_data;
84     AVIOContext *pb = s->pb;
85     const AVPixFmtDescriptor *pixdesc;
86     const CodecMime *mime = ff_id3v2_mime_tags;
87     AVDictionaryEntry *e;
88     const char *mimetype = NULL, *desc = "";
89     const AVStream *st = s->streams[pkt->stream_index];
90     int i, mimelen, desclen, type = 0, blocklen;
91 
92     if (!pkt->data)
93         return 0;
94 
95     while (mime->id != AV_CODEC_ID_NONE) {
96         if (mime->id == st->codecpar->codec_id) {
97             mimetype = mime->str;
98             break;
99         }
100         mime++;
101     }
102     if (!mimetype) {
103         av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot "
104                "write an attached picture.\n", st->index);
105         return AVERROR(EINVAL);
106     }
107     mimelen = strlen(mimetype);
108 
109     /* get the picture type */
110     e = av_dict_get(st->metadata, "comment", NULL, 0);
111     for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) {
112         if (!av_strcasecmp(e->value, ff_id3v2_picture_types[i])) {
113             type = i;
114             break;
115         }
116     }
117 
118     if ((c->attached_types & (1 << type)) & 0x6) {
119         av_log(s, AV_LOG_ERROR, "Duplicate attachment for type '%s'\n", ff_id3v2_picture_types[type]);
120         return AVERROR(EINVAL);
121     }
122 
123     if (type == 1 && (st->codecpar->codec_id != AV_CODEC_ID_PNG ||
124                       st->codecpar->width != 32 ||
125                       st->codecpar->height != 32)) {
126         av_log(s, AV_LOG_ERROR, "File icon attachment must be a 32x32 PNG");
127         return AVERROR(EINVAL);
128     }
129 
130     c->attached_types |= (1 << type);
131 
132     /* get the description */
133     if ((e = av_dict_get(st->metadata, "title", NULL, 0)))
134         desc = e->value;
135     desclen = strlen(desc);
136 
137     blocklen = 4 + 4 + mimelen + 4 + desclen + 4 + 4 + 4 + 4 + 4 + pkt->size;
138     if (blocklen >= 1<<24) {
139         av_log(s, AV_LOG_ERROR, "Picture block too big %d >= %d\n", blocklen, 1<<24);
140         return AVERROR(EINVAL);
141     }
142 
143     avio_w8(pb, 0x06);
144     avio_wb24(pb, blocklen);
145 
146     avio_wb32(pb, type);
147 
148     avio_wb32(pb, mimelen);
149     avio_write(pb, mimetype, mimelen);
150 
151     avio_wb32(pb, desclen);
152     avio_write(pb, desc, desclen);
153 
154     avio_wb32(pb, st->codecpar->width);
155     avio_wb32(pb, st->codecpar->height);
156     if ((pixdesc = av_pix_fmt_desc_get(st->codecpar->format)))
157         avio_wb32(pb, av_get_bits_per_pixel(pixdesc));
158     else
159         avio_wb32(pb, 0);
160     avio_wb32(pb, 0);
161 
162     avio_wb32(pb, pkt->size);
163     avio_write(pb, pkt->data, pkt->size);
164     return 0;
165 }
166 
flac_finish_header(struct AVFormatContext * s)167 static int flac_finish_header(struct AVFormatContext *s)
168 {
169     int i, ret, padding = s->metadata_header_padding;
170     if (padding < 0)
171         padding = 8192;
172     /* The FLAC specification states that 24 bits are used to represent the
173      * size of a metadata block so we must clip this value to 2^24-1. */
174     padding = av_clip_uintp2(padding, 24);
175 
176     for (i = 0; i < s->nb_streams; i++) {
177         AVStream *st = s->streams[i];
178         AVPacket *pkt = st->priv_data;
179         if (!pkt)
180             continue;
181         ret = flac_write_picture(s, pkt);
182         av_packet_unref(pkt);
183         if (ret < 0 && (s->error_recognition & AV_EF_EXPLODE))
184             return ret;
185     }
186 
187     ret = flac_write_block_comment(s->pb, &s->metadata, !padding,
188                                    s->flags & AVFMT_FLAG_BITEXACT);
189     if (ret)
190         return ret;
191 
192     /* The command line flac encoder defaults to placing a seekpoint
193      * every 10s.  So one might add padding to allow that later
194      * but there seems to be no simple way to get the duration here.
195      * So just add the amount requested by the user. */
196     if (padding)
197         flac_write_block_padding(s->pb, padding, 1);
198 
199     return 0;
200 }
201 
flac_init(struct AVFormatContext * s)202 static int flac_init(struct AVFormatContext *s)
203 {
204     AVCodecParameters *par;
205     FlacMuxerContext *c = s->priv_data;
206     int i;
207 
208     c->audio_stream_idx = -1;
209     for (i = 0; i < s->nb_streams; i++) {
210         AVStream *st = s->streams[i];
211         if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
212             if (c->audio_stream_idx >= 0 || st->codecpar->codec_id != AV_CODEC_ID_FLAC) {
213                 av_log(s, AV_LOG_ERROR, "Invalid audio stream. Exactly one FLAC "
214                        "audio stream is required.\n");
215                 return AVERROR(EINVAL);
216             }
217             par = s->streams[i]->codecpar;
218             c->audio_stream_idx = i;
219         } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
220             if (!(st->disposition & AV_DISPOSITION_ATTACHED_PIC)) {
221                 av_log(s, AV_LOG_WARNING, "Video stream #%d is not an attached picture. Ignoring\n", i);
222                 continue;
223             } else if (st->codecpar->codec_id == AV_CODEC_ID_GIF) {
224                 av_log(s, AV_LOG_ERROR, "GIF image support is not implemented.\n");
225                 return AVERROR_PATCHWELCOME;
226             } else if (!c->write_header) {
227                 av_log(s, AV_LOG_ERROR, "Can't write attached pictures without a header.\n");
228                 return AVERROR(EINVAL);
229             }
230             c->waiting_pics++;
231         } else {
232             av_log(s, AV_LOG_ERROR, "Only audio streams and pictures are allowed in FLAC.\n");
233             return AVERROR(EINVAL);
234         }
235     }
236     if (c->audio_stream_idx < 0) {
237         av_log(s, AV_LOG_ERROR, "No audio stream present.\n");
238         return AVERROR(EINVAL);
239     }
240 
241     /* add the channel layout tag */
242     if (par->ch_layout.order == AV_CHANNEL_ORDER_NATIVE &&
243         !(par->ch_layout.u.mask & ~0x3ffffULL) &&
244         !ff_flac_is_native_layout(par->ch_layout.u.mask)) {
245         AVDictionaryEntry *chmask = av_dict_get(s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK",
246                                                 NULL, 0);
247 
248         if (chmask) {
249             av_log(s, AV_LOG_WARNING, "A WAVEFORMATEXTENSIBLE_CHANNEL_MASK is "
250                    "already present, this muxer will not overwrite it.\n");
251         } else {
252             uint8_t buf[32];
253             snprintf(buf, sizeof(buf), "0x%"PRIx64, par->ch_layout.u.mask);
254             av_dict_set(&s->metadata, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0);
255         }
256     }
257 
258     return 0;
259 }
260 
flac_write_header(struct AVFormatContext * s)261 static int flac_write_header(struct AVFormatContext *s)
262 {
263     FlacMuxerContext *c = s->priv_data;
264     AVCodecParameters *par = s->streams[c->audio_stream_idx]->codecpar;
265     int ret;
266 
267     if (!c->write_header)
268         return 0;
269 
270     ret = ff_flac_write_header(s->pb, par->extradata,
271                                par->extradata_size, 0);
272     if (ret < 0)
273         return ret;
274 
275     if (!c->waiting_pics)
276         ret = flac_finish_header(s);
277 
278     return ret;
279 }
280 
flac_write_audio_packet(struct AVFormatContext * s,AVPacket * pkt)281 static int flac_write_audio_packet(struct AVFormatContext *s, AVPacket *pkt)
282 {
283     FlacMuxerContext *c = s->priv_data;
284     uint8_t *streaminfo;
285     size_t streaminfo_size;
286 
287     /* check for updated streaminfo */
288     streaminfo = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
289                                          &streaminfo_size);
290     if (streaminfo && streaminfo_size == FLAC_STREAMINFO_SIZE) {
291         memcpy(c->streaminfo, streaminfo, FLAC_STREAMINFO_SIZE);
292         c->updated_streaminfo = 1;
293     }
294 
295     if (pkt->size)
296         avio_write(s->pb, pkt->data, pkt->size);
297     return 0;
298 }
299 
flac_queue_flush(AVFormatContext * s)300 static int flac_queue_flush(AVFormatContext *s)
301 {
302     FlacMuxerContext *c = s->priv_data;
303     AVPacket *const pkt = ffformatcontext(s)->pkt;
304     int ret, write = 1;
305 
306     ret = flac_finish_header(s);
307     if (ret < 0)
308         write = 0;
309 
310     while (c->queue.head) {
311         avpriv_packet_list_get(&c->queue, pkt);
312         if (write && (ret = flac_write_audio_packet(s, pkt)) < 0)
313             write = 0;
314         av_packet_unref(pkt);
315     }
316     return ret;
317 }
318 
flac_write_trailer(struct AVFormatContext * s)319 static int flac_write_trailer(struct AVFormatContext *s)
320 {
321     AVIOContext *pb = s->pb;
322     int64_t file_size;
323     FlacMuxerContext *c = s->priv_data;
324 
325     if (c->waiting_pics) {
326         av_log(s, AV_LOG_WARNING, "No packets were sent for some of the "
327                "attached pictures.\n");
328         flac_queue_flush(s);
329     }
330 
331     if (!c->write_header || !c->updated_streaminfo)
332         return 0;
333 
334     if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
335         /* rewrite the STREAMINFO header block data */
336         file_size = avio_tell(pb);
337         avio_seek(pb, 8, SEEK_SET);
338         avio_write(pb, c->streaminfo, FLAC_STREAMINFO_SIZE);
339         avio_seek(pb, file_size, SEEK_SET);
340     } else {
341         av_log(s, AV_LOG_WARNING, "unable to rewrite FLAC header.\n");
342     }
343 
344     return 0;
345 }
346 
flac_deinit(struct AVFormatContext * s)347 static void flac_deinit(struct AVFormatContext *s)
348 {
349     FlacMuxerContext *c = s->priv_data;
350 
351     avpriv_packet_list_free(&c->queue);
352     for (unsigned i = 0; i < s->nb_streams; i++)
353         av_packet_free((AVPacket **)&s->streams[i]->priv_data);
354 }
355 
flac_write_packet(struct AVFormatContext * s,AVPacket * pkt)356 static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt)
357 {
358     FlacMuxerContext *c = s->priv_data;
359     int ret;
360 
361     if (pkt->stream_index == c->audio_stream_idx) {
362         if (c->waiting_pics) {
363             /* buffer audio packets until we get all the pictures */
364             ret = avpriv_packet_list_put(&c->queue, pkt, NULL, 0);
365             if (ret < 0) {
366                 av_log(s, AV_LOG_ERROR, "Out of memory in packet queue; skipping attached pictures\n");
367                 c->waiting_pics = 0;
368                 ret = flac_queue_flush(s);
369                 if (ret < 0)
370                     return ret;
371                 return flac_write_audio_packet(s, pkt);
372             }
373         } else
374             return flac_write_audio_packet(s, pkt);
375     } else {
376         AVStream *st = s->streams[pkt->stream_index];
377 
378         if (!c->waiting_pics ||
379             !(st->disposition & AV_DISPOSITION_ATTACHED_PIC))
380             return 0;
381 
382         /* warn only once for each stream */
383         if (st->nb_frames == 1) {
384             av_log(s, AV_LOG_WARNING, "Got more than one picture in stream %d,"
385                    " ignoring.\n", pkt->stream_index);
386         }
387         if (st->nb_frames >= 1)
388             return 0;
389 
390         st->priv_data = av_packet_clone(pkt);
391         if (!st->priv_data)
392             av_log(s, AV_LOG_ERROR, "Out of memory queueing an attached picture; skipping\n");
393         c->waiting_pics--;
394 
395         /* flush the buffered audio packets */
396         if (!c->waiting_pics &&
397             (ret = flac_queue_flush(s)) < 0)
398             return ret;
399     }
400 
401     return 0;
402 }
403 
404 static const AVOption flacenc_options[] = {
405     { "write_header", "Write the file header", offsetof(FlacMuxerContext, write_header), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM },
406     { NULL },
407 };
408 
409 static const AVClass flac_muxer_class = {
410     .class_name = "flac muxer",
411     .item_name  = av_default_item_name,
412     .option     = flacenc_options,
413     .version    = LIBAVUTIL_VERSION_INT,
414 };
415 
416 const AVOutputFormat ff_flac_muxer = {
417     .name              = "flac",
418     .long_name         = NULL_IF_CONFIG_SMALL("raw FLAC"),
419     .priv_data_size    = sizeof(FlacMuxerContext),
420     .mime_type         = "audio/x-flac",
421     .extensions        = "flac",
422     .audio_codec       = AV_CODEC_ID_FLAC,
423     .video_codec       = AV_CODEC_ID_PNG,
424     .init              = flac_init,
425     .write_header      = flac_write_header,
426     .write_packet      = flac_write_packet,
427     .write_trailer     = flac_write_trailer,
428     .deinit            = flac_deinit,
429     .flags             = AVFMT_NOTIMESTAMPS,
430     .priv_class        = &flac_muxer_class,
431 };
432