Libav
|
00001 /* 00002 * Creative Voice File muxer. 00003 * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org> 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 "voc.h" 00023 00024 00025 typedef struct voc_enc_context { 00026 int param_written; 00027 } VocEncContext; 00028 00029 static int voc_write_header(AVFormatContext *s) 00030 { 00031 ByteIOContext *pb = s->pb; 00032 const int header_size = 26; 00033 const int version = 0x0114; 00034 00035 if (s->nb_streams != 1 00036 || s->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) 00037 return AVERROR_PATCHWELCOME; 00038 00039 put_buffer(pb, ff_voc_magic, sizeof(ff_voc_magic) - 1); 00040 put_le16(pb, header_size); 00041 put_le16(pb, version); 00042 put_le16(pb, ~version + 0x1234); 00043 00044 return 0; 00045 } 00046 00047 static int voc_write_packet(AVFormatContext *s, AVPacket *pkt) 00048 { 00049 VocEncContext *voc = s->priv_data; 00050 AVCodecContext *enc = s->streams[0]->codec; 00051 ByteIOContext *pb = s->pb; 00052 00053 if (!voc->param_written) { 00054 if (enc->codec_tag > 0xFF) { 00055 put_byte(pb, VOC_TYPE_NEW_VOICE_DATA); 00056 put_le24(pb, pkt->size + 12); 00057 put_le32(pb, enc->sample_rate); 00058 put_byte(pb, enc->bits_per_coded_sample); 00059 put_byte(pb, enc->channels); 00060 put_le16(pb, enc->codec_tag); 00061 put_le32(pb, 0); 00062 } else { 00063 if (s->streams[0]->codec->channels > 1) { 00064 put_byte(pb, VOC_TYPE_EXTENDED); 00065 put_le24(pb, 4); 00066 put_le16(pb, 65536-256000000/(enc->sample_rate*enc->channels)); 00067 put_byte(pb, enc->codec_tag); 00068 put_byte(pb, enc->channels - 1); 00069 } 00070 put_byte(pb, VOC_TYPE_VOICE_DATA); 00071 put_le24(pb, pkt->size + 2); 00072 put_byte(pb, 256 - 1000000 / enc->sample_rate); 00073 put_byte(pb, enc->codec_tag); 00074 } 00075 voc->param_written = 1; 00076 } else { 00077 put_byte(pb, VOC_TYPE_VOICE_DATA_CONT); 00078 put_le24(pb, pkt->size); 00079 } 00080 00081 put_buffer(pb, pkt->data, pkt->size); 00082 return 0; 00083 } 00084 00085 static int voc_write_trailer(AVFormatContext *s) 00086 { 00087 put_byte(s->pb, 0); 00088 return 0; 00089 } 00090 00091 AVOutputFormat voc_muxer = { 00092 "voc", 00093 NULL_IF_CONFIG_SMALL("Creative Voice file format"), 00094 "audio/x-voc", 00095 "voc", 00096 sizeof(VocEncContext), 00097 CODEC_ID_PCM_U8, 00098 CODEC_ID_NONE, 00099 voc_write_header, 00100 voc_write_packet, 00101 voc_write_trailer, 00102 .codec_tag=(const AVCodecTag* const []){ff_voc_codec_tags, 0}, 00103 };