2 * Creative Voice File muxer.
3 * Copyright (c) 2006 Aurelien Jacobs <aurel@gnuage.org>
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 typedef struct voc_enc_context
{
30 static int voc_write_header(AVFormatContext
*s
)
32 AVIOContext
*pb
= s
->pb
;
33 AVCodecContext
*enc
= s
->streams
[0]->codec
;
34 const int header_size
= 26;
35 const int version
= 0x0114;
37 if (s
->nb_streams
!= 1
38 || s
->streams
[0]->codec
->codec_type
!= AVMEDIA_TYPE_AUDIO
)
39 return AVERROR_PATCHWELCOME
;
41 if (!enc
->codec_tag
&& enc
->codec_id
!= AV_CODEC_ID_PCM_U8
) {
42 av_log(s
, AV_LOG_ERROR
, "unsupported codec\n");
43 return AVERROR(EINVAL
);
46 avio_write(pb
, ff_voc_magic
, sizeof(ff_voc_magic
) - 1);
47 avio_wl16(pb
, header_size
);
48 avio_wl16(pb
, version
);
49 avio_wl16(pb
, ~version
+ 0x1234);
54 static int voc_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
56 VocEncContext
*voc
= s
->priv_data
;
57 AVCodecContext
*enc
= s
->streams
[0]->codec
;
58 AVIOContext
*pb
= s
->pb
;
60 if (!voc
->param_written
) {
61 if (enc
->codec_tag
> 3) {
62 avio_w8(pb
, VOC_TYPE_NEW_VOICE_DATA
);
63 avio_wl24(pb
, pkt
->size
+ 12);
64 avio_wl32(pb
, enc
->sample_rate
);
65 avio_w8(pb
, enc
->bits_per_coded_sample
);
66 avio_w8(pb
, enc
->channels
);
67 avio_wl16(pb
, enc
->codec_tag
);
70 if (s
->streams
[0]->codec
->channels
> 1) {
71 avio_w8(pb
, VOC_TYPE_EXTENDED
);
73 avio_wl16(pb
, 65536-(256000000 + enc
->sample_rate
*enc
->channels
/2)/(enc
->sample_rate
*enc
->channels
));
74 avio_w8(pb
, enc
->codec_tag
);
75 avio_w8(pb
, enc
->channels
- 1);
77 avio_w8(pb
, VOC_TYPE_VOICE_DATA
);
78 avio_wl24(pb
, pkt
->size
+ 2);
79 avio_w8(pb
, 256 - (1000000 + enc
->sample_rate
/2) / enc
->sample_rate
);
80 avio_w8(pb
, enc
->codec_tag
);
82 voc
->param_written
= 1;
84 avio_w8(pb
, VOC_TYPE_VOICE_DATA_CONT
);
85 avio_wl24(pb
, pkt
->size
);
88 avio_write(pb
, pkt
->data
, pkt
->size
);
92 static int voc_write_trailer(AVFormatContext
*s
)
98 AVOutputFormat ff_voc_muxer
= {
100 .long_name
= NULL_IF_CONFIG_SMALL("Creative Voice"),
101 .mime_type
= "audio/x-voc",
103 .priv_data_size
= sizeof(VocEncContext
),
104 .audio_codec
= AV_CODEC_ID_PCM_S16LE
,
105 .video_codec
= AV_CODEC_ID_NONE
,
106 .write_header
= voc_write_header
,
107 .write_packet
= voc_write_packet
,
108 .write_trailer
= voc_write_trailer
,
109 .codec_tag
= (const AVCodecTag
* const []){ ff_voc_codec_tags
, 0 },
110 .flags
= AVFMT_NOTIMESTAMPS
,