cbfe5bee |
/*
* SoX native format muxer
* Copyright (c) 2009 Daniel Verkamp <daniel@drv.nu>
*
* Based on libSoX sox-fmt.c
* Copyright (c) 2008 robs@users.sourceforge.net
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/** |
ba87f080 |
* @file |
f6f95d4e |
* SoX native format muxer |
cbfe5bee |
* @author Daniel Verkamp |
bee6d2fd |
* @see http://wiki.multimedia.cx/index.php?title=SoX_native_intermediate_format |
cbfe5bee |
*/
#include "libavutil/intreadwrite.h" |
3383a53e |
#include "libavutil/intfloat.h" |
d2d67e42 |
#include "libavutil/dict.h" |
cbfe5bee |
#include "avformat.h" |
0abdb293 |
#include "avio_internal.h" |
8ad010a7 |
#include "rawenc.h" |
cbfe5bee |
#include "sox.h"
|
daf8cf35 |
typedef struct SoXContext { |
cbfe5bee |
int64_t header_size;
} SoXContext;
static int sox_write_header(AVFormatContext *s)
{
SoXContext *sox = s->priv_data; |
ae628ec1 |
AVIOContext *pb = s->pb; |
9200514a |
AVCodecParameters *par = s->streams[0]->codecpar; |
d2d67e42 |
AVDictionaryEntry *comment; |
cbfe5bee |
size_t comment_len = 0, comment_size;
|
d2d67e42 |
comment = av_dict_get(s->metadata, "comment", NULL, 0); |
cbfe5bee |
if (comment)
comment_len = strlen(comment->value); |
a4912aa6 |
comment_size = FFALIGN(comment_len, 8); |
cbfe5bee |
sox->header_size = SOX_FIXED_HDR + comment_size;
|
9200514a |
if (par->codec_id == AV_CODEC_ID_PCM_S32LE) { |
0abdb293 |
ffio_wfourcc(pb, ".SoX"); |
77eb5504 |
avio_wl32(pb, sox->header_size);
avio_wl64(pb, 0); /* number of samples */ |
9200514a |
avio_wl64(pb, av_double2int(par->sample_rate));
avio_wl32(pb, par->channels); |
77eb5504 |
avio_wl32(pb, comment_size); |
9200514a |
} else if (par->codec_id == AV_CODEC_ID_PCM_S32BE) { |
0abdb293 |
ffio_wfourcc(pb, "XoS."); |
77eb5504 |
avio_wb32(pb, sox->header_size);
avio_wb64(pb, 0); /* number of samples */ |
9200514a |
avio_wb64(pb, av_double2int(par->sample_rate));
avio_wb32(pb, par->channels); |
77eb5504 |
avio_wb32(pb, comment_size); |
cbfe5bee |
} else {
av_log(s, AV_LOG_ERROR, "invalid codec; use pcm_s32le or pcm_s32be\n"); |
0ddb0516 |
return AVERROR(EINVAL); |
cbfe5bee |
}
if (comment_len) |
77eb5504 |
avio_write(pb, comment->value, comment_len); |
cbfe5bee |
|
09401694 |
ffio_fill(pb, 0, comment_size - comment_len); |
cbfe5bee |
|
b7f2fdde |
avio_flush(pb); |
cbfe5bee |
return 0;
}
static int sox_write_trailer(AVFormatContext *s)
{
SoXContext *sox = s->priv_data; |
ae628ec1 |
AVIOContext *pb = s->pb; |
9200514a |
AVCodecParameters *par = s->streams[0]->codecpar; |
cbfe5bee |
|
83548fe8 |
if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { |
cbfe5bee |
/* update number of samples */ |
a2704c97 |
int64_t file_size = avio_tell(pb); |
cbfe5bee |
int64_t num_samples = (file_size - sox->header_size - 4LL) >> 2LL; |
6b4aa5da |
avio_seek(pb, 8, SEEK_SET); |
9200514a |
if (par->codec_id == AV_CODEC_ID_PCM_S32LE) { |
77eb5504 |
avio_wl64(pb, num_samples); |
cbfe5bee |
} else |
77eb5504 |
avio_wb64(pb, num_samples); |
6b4aa5da |
avio_seek(pb, file_size, SEEK_SET); |
cbfe5bee |
|
b7f2fdde |
avio_flush(pb); |
cbfe5bee |
}
return 0;
}
|
c6610a21 |
AVOutputFormat ff_sox_muxer = { |
dfc2c4d9 |
.name = "sox", |
6774247a |
.long_name = NULL_IF_CONFIG_SMALL("SoX native"), |
dfc2c4d9 |
.extensions = "sox",
.priv_data_size = sizeof(SoXContext), |
36ef5369 |
.audio_codec = AV_CODEC_ID_PCM_S32LE,
.video_codec = AV_CODEC_ID_NONE, |
dfc2c4d9 |
.write_header = sox_write_header, |
8ad010a7 |
.write_packet = ff_raw_write_packet, |
dfc2c4d9 |
.write_trailer = sox_write_trailer, |
f792d3cb |
.flags = AVFMT_NOTIMESTAMPS, |
cbfe5bee |
}; |