Line data Source code
1 : /*
2 : * SoX native format muxer
3 : * Copyright (c) 2009 Daniel Verkamp <daniel@drv.nu>
4 : *
5 : * Based on libSoX sox-fmt.c
6 : * Copyright (c) 2008 robs@users.sourceforge.net
7 : *
8 : * This file is part of FFmpeg.
9 : *
10 : * FFmpeg is free software; you can redistribute it and/or
11 : * modify it under the terms of the GNU Lesser General Public
12 : * License as published by the Free Software Foundation; either
13 : * version 2.1 of the License, or (at your option) any later version.
14 : *
15 : * FFmpeg is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 : * Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with FFmpeg; if not, write to the Free Software
22 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 : */
24 :
25 : /**
26 : * @file
27 : * SoX native format muxer
28 : * @author Daniel Verkamp
29 : * @see http://wiki.multimedia.cx/index.php?title=SoX_native_intermediate_format
30 : */
31 :
32 : #include "libavutil/intreadwrite.h"
33 : #include "libavutil/intfloat.h"
34 : #include "libavutil/dict.h"
35 : #include "avformat.h"
36 : #include "avio_internal.h"
37 : #include "rawenc.h"
38 : #include "sox.h"
39 :
40 : typedef struct SoXContext {
41 : int64_t header_size;
42 : } SoXContext;
43 :
44 1 : static int sox_write_header(AVFormatContext *s)
45 : {
46 1 : SoXContext *sox = s->priv_data;
47 1 : AVIOContext *pb = s->pb;
48 1 : AVCodecParameters *par = s->streams[0]->codecpar;
49 : AVDictionaryEntry *comment;
50 1 : size_t comment_len = 0, comment_size;
51 :
52 1 : comment = av_dict_get(s->metadata, "comment", NULL, 0);
53 1 : if (comment)
54 0 : comment_len = strlen(comment->value);
55 1 : comment_size = FFALIGN(comment_len, 8);
56 :
57 1 : sox->header_size = SOX_FIXED_HDR + comment_size;
58 :
59 1 : if (par->codec_id == AV_CODEC_ID_PCM_S32LE) {
60 1 : ffio_wfourcc(pb, ".SoX");
61 1 : avio_wl32(pb, sox->header_size);
62 1 : avio_wl64(pb, 0); /* number of samples */
63 1 : avio_wl64(pb, av_double2int(par->sample_rate));
64 1 : avio_wl32(pb, par->channels);
65 1 : avio_wl32(pb, comment_size);
66 0 : } else if (par->codec_id == AV_CODEC_ID_PCM_S32BE) {
67 0 : ffio_wfourcc(pb, "XoS.");
68 0 : avio_wb32(pb, sox->header_size);
69 0 : avio_wb64(pb, 0); /* number of samples */
70 0 : avio_wb64(pb, av_double2int(par->sample_rate));
71 0 : avio_wb32(pb, par->channels);
72 0 : avio_wb32(pb, comment_size);
73 : } else {
74 0 : av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n");
75 0 : return AVERROR(EINVAL);
76 : }
77 :
78 1 : if (comment_len)
79 0 : avio_write(pb, comment->value, comment_len);
80 :
81 1 : ffio_fill(pb, 0, comment_size - comment_len);
82 :
83 1 : avio_flush(pb);
84 :
85 1 : return 0;
86 : }
87 :
88 1 : static int sox_write_trailer(AVFormatContext *s)
89 : {
90 1 : SoXContext *sox = s->priv_data;
91 1 : AVIOContext *pb = s->pb;
92 1 : AVCodecParameters *par = s->streams[0]->codecpar;
93 :
94 1 : if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
95 : /* update number of samples */
96 1 : int64_t file_size = avio_tell(pb);
97 1 : int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL;
98 1 : avio_seek(pb, 8, SEEK_SET);
99 1 : if (par->codec_id == AV_CODEC_ID_PCM_S32LE) {
100 1 : avio_wl64(pb, num_samples);
101 : } else
102 0 : avio_wb64(pb, num_samples);
103 1 : avio_seek(pb, file_size, SEEK_SET);
104 :
105 1 : avio_flush(pb);
106 : }
107 :
108 1 : return 0;
109 : }
110 :
111 : AVOutputFormat ff_sox_muxer = {
112 : .name = "sox",
113 : .long_name = NULL_IF_CONFIG_SMALL("SoX native"),
114 : .extensions = "sox",
115 : .priv_data_size = sizeof(SoXContext),
116 : .audio_codec = AV_CODEC_ID_PCM_S32LE,
117 : .video_codec = AV_CODEC_ID_NONE,
118 : .write_header = sox_write_header,
119 : .write_packet = ff_raw_write_packet,
120 : .write_trailer = sox_write_trailer,
121 : .flags = AVFMT_NOTIMESTAMPS,
122 : };
|