Libav
|
00001 /* 00002 * raw FLAC muxer 00003 * Copyright (c) 2006-2009 Justin Ruggles 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 /* The command line flac encoder defaults to placing a seekpoint 00081 * every 10s. So one might add padding to allow that later 00082 * but there seems to be no simple way to get the duration here. 00083 * So let's try the flac default of 8192 bytes */ 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 /* rewrite the STREAMINFO header block data */ 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 };