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 "metadata.h"
00026 #include "vorbiscomment.h"
00027 #include "libavcodec/bytestream.h"
00028
00029
00030 static int flac_write_block_padding(ByteIOContext *pb, unsigned int n_padding_bytes,
00031 int last_block)
00032 {
00033 put_byte(pb, last_block ? 0x81 : 0x01);
00034 put_be24(pb, n_padding_bytes);
00035 while (n_padding_bytes > 0) {
00036 put_byte(pb, 0);
00037 n_padding_bytes--;
00038 }
00039 return 0;
00040 }
00041
00042 static int flac_write_block_comment(ByteIOContext *pb, AVMetadata *m,
00043 int last_block, int bitexact)
00044 {
00045 const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
00046 unsigned int len, count;
00047 uint8_t *p, *p0;
00048
00049 len = ff_vorbiscomment_length(m, vendor, &count);
00050 p0 = av_malloc(len+4);
00051 if (!p0)
00052 return AVERROR(ENOMEM);
00053 p = p0;
00054
00055 bytestream_put_byte(&p, last_block ? 0x84 : 0x04);
00056 bytestream_put_be24(&p, len);
00057 ff_vorbiscomment_write(&p, m, vendor, count);
00058
00059 put_buffer(pb, p0, len+4);
00060 av_freep(&p0);
00061 p = NULL;
00062
00063 return 0;
00064 }
00065
00066 static int flac_write_header(struct AVFormatContext *s)
00067 {
00068 int ret;
00069 AVCodecContext *codec = s->streams[0]->codec;
00070
00071 ret = ff_flac_write_header(s->pb, codec, 0);
00072 if (ret)
00073 return ret;
00074
00075 ret = flac_write_block_comment(s->pb, s->metadata, 0,
00076 codec->flags & CODEC_FLAG_BITEXACT);
00077 if (ret)
00078 return ret;
00079
00080
00081
00082
00083
00084 flac_write_block_padding(s->pb, 8192, 1);
00085
00086 return ret;
00087 }
00088
00089 static int flac_write_trailer(struct AVFormatContext *s)
00090 {
00091 ByteIOContext *pb = s->pb;
00092 uint8_t *streaminfo;
00093 enum FLACExtradataFormat format;
00094 int64_t file_size;
00095
00096 if (!ff_flac_is_extradata_valid(s->streams[0]->codec, &format, &streaminfo))
00097 return -1;
00098
00099 if (!url_is_streamed(pb)) {
00100
00101 file_size = url_ftell(pb);
00102 url_fseek(pb, 8, SEEK_SET);
00103 put_buffer(pb, streaminfo, FLAC_STREAMINFO_SIZE);
00104 url_fseek(pb, file_size, SEEK_SET);
00105 put_flush_packet(pb);
00106 } else {
00107 av_log(s, AV_LOG_WARNING, "unable to rewrite FLAC header.\n");
00108 }
00109 return 0;
00110 }
00111
00112 static int flac_write_packet(struct AVFormatContext *s, AVPacket *pkt)
00113 {
00114 put_buffer(s->pb, pkt->data, pkt->size);
00115 put_flush_packet(s->pb);
00116 return 0;
00117 }
00118
00119 AVOutputFormat flac_muxer = {
00120 "flac",
00121 NULL_IF_CONFIG_SMALL("raw FLAC"),
00122 "audio/x-flac",
00123 "flac",
00124 0,
00125 CODEC_ID_FLAC,
00126 CODEC_ID_NONE,
00127 flac_write_header,
00128 flac_write_packet,
00129 flac_write_trailer,
00130 .flags= AVFMT_NOTIMESTAMPS,
00131 .metadata_conv = ff_vorbiscomment_metadata_conv,
00132 };