00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavcodec/flac.h"
00023 #include "avformat.h"
00024 #include "flacenc.h"
00025 #include "vorbiscomment.h"
00026 #include "libavcodec/bytestream.h"
00027
00028
00029 static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_bytes,
00030 int last_block)
00031 {
00032 avio_w8(pb, last_block ? 0x81 : 0x01);
00033 avio_wb24(pb, n_padding_bytes);
00034 while (n_padding_bytes > 0) {
00035 avio_w8(pb, 0);
00036 n_padding_bytes--;
00037 }
00038 return 0;
00039 }
00040
00041 static int flac_write_block_comment(AVIOContext *pb, AVDictionary **m,
00042 int last_block, int bitexact)
00043 {
00044 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
00045 unsigned int len, count;
00046 uint8_t *p, *p0;
00047
00048 ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
00049
00050 len = ff_vorbiscomment_length(*m, vendor, &count);
00051 p0 = av_malloc(len+4);
00052 if (!p0)
00053 return AVERROR(ENOMEM);
00054 p = p0;
00055
00056 bytestream_put_byte(&p, last_block ? 0x84 : 0x04);
00057 bytestream_put_be24(&p, len);
00058 ff_vorbiscomment_write(&p, m, vendor, count);
00059
00060 avio_write(pb, p0, len+4);
00061 av_freep(&p0);
00062 p = NULL;
00063
00064 return 0;
00065 }
00066
00067 static int flac_write_header(struct AVFormatContext *s)
00068 {
00069 int ret;
00070 AVCodecContext *codec = s->streams[0]->codec;
00071
00072 if (s->nb_streams > 1) {
00073 av_log(s, AV_LOG_ERROR, "only one stream is supported\n");
00074 return AVERROR(EINVAL);
00075 }
00076 if (codec->codec_id != AV_CODEC_ID_FLAC) {
00077 av_log(s, AV_LOG_ERROR, "unsupported codec\n");
00078 return AVERROR(EINVAL);
00079 }
00080
00081 ret = ff_flac_write_header(s->pb, codec, 0);
00082 if (ret)
00083 return ret;
00084
00085 ret = flac_write_block_comment(s->pb, &s->metadata, 0,
00086 codec->flags & CODEC_FLAG_BITEXACT);
00087 if (ret)
00088 return ret;
00089
00090
00091
00092
00093
00094 flac_write_block_padding(s->pb, 8192, 1);
00095
00096 return ret;
00097 }
00098
00099 static int flac_write_trailer(struct AVFormatContext *s)
00100 {
00101 AVIOContext *pb = s->pb;
00102 uint8_t *streaminfo;
00103 enum FLACExtradataFormat format;
00104 int64_t file_size;
00105
00106 if (!avpriv_flac_is_extradata_valid(s->streams[0]->codec, &format, &streaminfo))
00107 return -1;
00108
00109 if (pb->seekable) {
00110
00111 file_size = avio_tell(pb);
00112 avio_seek(pb, 8, SEEK_SET);
00113 avio_write(pb, streaminfo, FLAC_STREAMINFO_SIZE);
00114 avio_seek(pb, file_size, SEEK_SET);
00115 avio_flush(pb);
00116 } else {
00117 av_log(s, AV_LOG_WARNING, "unable to rewrite FLAC header.\n");
00118 }
00119 return 0;
00120 }
00121
00122 static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt)
00123 {
00124 avio_write(s->pb, pkt->data, pkt->size);
00125 avio_flush(s->pb);
00126 return 0;
00127 }
00128
00129 AVOutputFormat ff_flac_muxer = {
00130 .name = "flac",
00131 .long_name = NULL_IF_CONFIG_SMALL("raw FLAC"),
00132 .mime_type = "audio/x-flac",
00133 .extensions = "flac",
00134 .audio_codec = AV_CODEC_ID_FLAC,
00135 .video_codec = AV_CODEC_ID_NONE,
00136 .write_header = flac_write_header,
00137 .write_packet = flac_write_packet,
00138 .write_trailer = flac_write_trailer,
00139 .flags = AVFMT_NOTIMESTAMPS,
00140 };