Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
soxenc.c
Go to the documentation of this file.
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 Libav.
9
*
10
* Libav 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
* Libav 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 Libav; if not, write to the Free Software
22
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
*/
24
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 "
sox.h
"
38
39
typedef
struct
{
40
int64_t
header_size
;
41
}
SoXContext
;
42
43
static
int
sox_write_header
(
AVFormatContext
*s)
44
{
45
SoXContext
*sox = s->
priv_data
;
46
AVIOContext
*pb = s->
pb
;
47
AVCodecContext
*enc = s->
streams
[0]->
codec
;
48
AVDictionaryEntry
*comment;
49
size_t
comment_len = 0, comment_size;
50
51
comment =
av_dict_get
(s->
metadata
,
"comment"
,
NULL
, 0);
52
if
(comment)
53
comment_len = strlen(comment->
value
);
54
comment_size = (comment_len + 7) & ~7;
55
56
sox->
header_size
=
SOX_FIXED_HDR
+ comment_size;
57
58
if
(enc->
codec_id
==
AV_CODEC_ID_PCM_S32LE
) {
59
ffio_wfourcc
(pb,
".SoX"
);
60
avio_wl32
(pb, sox->
header_size
);
61
avio_wl64
(pb, 0);
/* number of samples */
62
avio_wl64
(pb,
av_double2int
(enc->
sample_rate
));
63
avio_wl32
(pb, enc->
channels
);
64
avio_wl32
(pb, comment_size);
65
}
else
if
(enc->
codec_id
==
AV_CODEC_ID_PCM_S32BE
) {
66
ffio_wfourcc
(pb,
"XoS."
);
67
avio_wb32
(pb, sox->
header_size
);
68
avio_wb64
(pb, 0);
/* number of samples */
69
avio_wb64
(pb,
av_double2int
(enc->
sample_rate
));
70
avio_wb32
(pb, enc->
channels
);
71
avio_wb32
(pb, comment_size);
72
}
else
{
73
av_log
(s,
AV_LOG_ERROR
,
"invalid codec; use pcm_s32le or pcm_s32be\n"
);
74
return
-1;
75
}
76
77
if
(comment_len)
78
avio_write
(pb, comment->
value
, comment_len);
79
80
for
( ; comment_size > comment_len; comment_len++)
81
avio_w8
(pb, 0);
82
83
avio_flush
(pb);
84
85
return
0;
86
}
87
88
static
int
sox_write_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
89
{
90
AVIOContext
*pb = s->
pb
;
91
avio_write
(pb, pkt->
data
, pkt->
size
);
92
return
0;
93
}
94
95
static
int
sox_write_trailer
(
AVFormatContext
*s)
96
{
97
SoXContext
*sox = s->
priv_data
;
98
AVIOContext
*pb = s->
pb
;
99
AVCodecContext
*enc = s->
streams
[0]->
codec
;
100
101
if
(s->
pb
->
seekable
) {
102
/* update number of samples */
103
int64_t file_size =
avio_tell
(pb);
104
int64_t num_samples = (file_size - sox->
header_size
- 4LL) >> 2LL;
105
avio_seek
(pb, 8, SEEK_SET);
106
if
(enc->
codec_id
==
AV_CODEC_ID_PCM_S32LE
) {
107
avio_wl64
(pb, num_samples);
108
}
else
109
avio_wb64
(pb, num_samples);
110
avio_seek
(pb, file_size, SEEK_SET);
111
112
avio_flush
(pb);
113
}
114
115
return
0;
116
}
117
118
AVOutputFormat
ff_sox_muxer
= {
119
.
name
=
"sox"
,
120
.long_name =
NULL_IF_CONFIG_SMALL
(
"SoX native"
),
121
.extensions =
"sox"
,
122
.priv_data_size =
sizeof
(
SoXContext
),
123
.audio_codec =
AV_CODEC_ID_PCM_S32LE
,
124
.video_codec =
AV_CODEC_ID_NONE
,
125
.
write_header
=
sox_write_header
,
126
.
write_packet
=
sox_write_packet
,
127
.
write_trailer
=
sox_write_trailer
,
128
};