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