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 #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 .name = "voc",
00094 .long_name = NULL_IF_CONFIG_SMALL("Creative Voice file format"),
00095 .mime_type = "audio/x-voc",
00096 .extensions = "voc",
00097 .priv_data_size = sizeof(VocEncContext),
00098 .audio_codec = CODEC_ID_PCM_U8,
00099 .video_codec = CODEC_ID_NONE,
00100 .write_header = voc_write_header,
00101 .write_packet = voc_write_packet,
00102 .write_trailer = voc_write_trailer,
00103 .codec_tag=(const AVCodecTag* const []){ff_voc_codec_tags, 0},
00104 };