00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
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 != CODEC_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 };