Statistics
| Branch: | Revision:

ffmpeg / libavformat / soxdec.c @ e356fc57

History | View | Annotate | Download (4.57 KB)

1 cbfe5bee Daniel Verkamp
/*
2
 * SoX native format demuxer
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
 * SoX native format demuxer
27 ba87f080 Diego Biurrun
 * @file
28 cbfe5bee Daniel Verkamp
 * @author Daniel Verkamp
29
 * @sa http://wiki.multimedia.cx/index.php?title=SoX_native_intermediate_format
30
 */
31
32
#include "libavutil/intreadwrite.h"
33
#include "avformat.h"
34 e94204df Aurelien Jacobs
#include "pcm.h"
35 cbfe5bee Daniel Verkamp
#include "sox.h"
36
37
static int sox_probe(AVProbeData *p)
38
{
39
    if (AV_RL32(p->buf) == SOX_TAG || AV_RB32(p->buf) == SOX_TAG)
40
        return AVPROBE_SCORE_MAX;
41
    return 0;
42
}
43
44
static int sox_read_header(AVFormatContext *s,
45
                           AVFormatParameters *ap)
46
{
47 ae628ec1 Anton Khirnov
    AVIOContext *pb = s->pb;
48 cbfe5bee Daniel Verkamp
    unsigned header_size, comment_size;
49
    double sample_rate, sample_rate_frac;
50
    AVStream *st;
51
52
    st = av_new_stream(s, 0);
53
    if (!st)
54
        return AVERROR(ENOMEM);
55
56 72415b2a Stefano Sabatini
    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
57 cbfe5bee Daniel Verkamp
58 b7effd4e Anton Khirnov
    if (avio_rl32(pb) == SOX_TAG) {
59 cbfe5bee Daniel Verkamp
        st->codec->codec_id = CODEC_ID_PCM_S32LE;
60 b7effd4e Anton Khirnov
        header_size         = avio_rl32(pb);
61 e356fc57 Anton Khirnov
        avio_seek(pb, 8, SEEK_CUR); /* sample count */
62 b7effd4e Anton Khirnov
        sample_rate         = av_int2dbl(avio_rl64(pb));
63
        st->codec->channels = avio_rl32(pb);
64
        comment_size        = avio_rl32(pb);
65 cbfe5bee Daniel Verkamp
    } else {
66
        st->codec->codec_id = CODEC_ID_PCM_S32BE;
67 b7effd4e Anton Khirnov
        header_size         = avio_rb32(pb);
68 e356fc57 Anton Khirnov
        avio_seek(pb, 8, SEEK_CUR); /* sample count */
69 b7effd4e Anton Khirnov
        sample_rate         = av_int2dbl(avio_rb64(pb));
70
        st->codec->channels = avio_rb32(pb);
71
        comment_size        = avio_rb32(pb);
72 cbfe5bee Daniel Verkamp
    }
73
74
    if (comment_size > 0xFFFFFFFFU - SOX_FIXED_HDR - 4U) {
75
        av_log(s, AV_LOG_ERROR, "invalid comment size (%u)\n", comment_size);
76
        return -1;
77
    }
78
79
    if (sample_rate <= 0 || sample_rate > INT_MAX) {
80
        av_log(s, AV_LOG_ERROR, "invalid sample rate (%f)\n", sample_rate);
81
        return -1;
82
    }
83
84
    sample_rate_frac = sample_rate - floor(sample_rate);
85
    if (sample_rate_frac)
86
        av_log(s, AV_LOG_WARNING,
87
               "truncating fractional part of sample rate (%f)\n",
88
               sample_rate_frac);
89
90
    if ((header_size + 4) & 7 || header_size < SOX_FIXED_HDR + comment_size
91
        || st->codec->channels > 65535) /* Reserve top 16 bits */ {
92
        av_log(s, AV_LOG_ERROR, "invalid header\n");
93
        return -1;
94
    }
95
96 12ad6671 Michael Niedermayer
    if (comment_size && comment_size < UINT_MAX) {
97
        char *comment = av_malloc(comment_size+1);
98 b7effd4e Anton Khirnov
        if (avio_read(pb, comment, comment_size) != comment_size) {
99 cbfe5bee Daniel Verkamp
            av_freep(&comment);
100 5ae092ee Stefano Sabatini
            return AVERROR(EIO);
101 cbfe5bee Daniel Verkamp
        }
102 12ad6671 Michael Niedermayer
        comment[comment_size] = 0;
103
104
        av_metadata_set2(&s->metadata, "comment", comment,
105
                               AV_METADATA_DONT_STRDUP_VAL);
106 cbfe5bee Daniel Verkamp
    }
107
108 e356fc57 Anton Khirnov
    avio_seek(pb, header_size - SOX_FIXED_HDR - comment_size, SEEK_CUR);
109 cbfe5bee Daniel Verkamp
110
    st->codec->sample_rate           = sample_rate;
111
    st->codec->bits_per_coded_sample = 32;
112
    st->codec->bit_rate              = st->codec->sample_rate *
113
                                       st->codec->bits_per_coded_sample *
114
                                       st->codec->channels;
115 5a1e202b Phil Rutschman
    st->codec->block_align           = st->codec->bits_per_coded_sample *
116
                                       st->codec->channels / 8;
117 cbfe5bee Daniel Verkamp
118
    av_set_pts_info(st, 64, 1, st->codec->sample_rate);
119
120
    return 0;
121
}
122
123 5a1e202b Phil Rutschman
#define SOX_SAMPLES 1024
124 cbfe5bee Daniel Verkamp
125
static int sox_read_packet(AVFormatContext *s,
126
                           AVPacket *pkt)
127
{
128 5a1e202b Phil Rutschman
    int ret, size;
129 cbfe5bee Daniel Verkamp
130
    if (url_feof(s->pb))
131
        return AVERROR_EOF;
132
133 5a1e202b Phil Rutschman
    size = SOX_SAMPLES*s->streams[0]->codec->block_align;
134
    ret = av_get_packet(s->pb, pkt, size);
135 cbfe5bee Daniel Verkamp
    if (ret < 0)
136
        return AVERROR(EIO);
137
    pkt->stream_index = 0;
138
    pkt->size = ret;
139
140
    return 0;
141
}
142
143 c6610a21 Diego Elio Pettenò
AVInputFormat ff_sox_demuxer = {
144 cbfe5bee Daniel Verkamp
    "sox",
145
    NULL_IF_CONFIG_SMALL("SoX native format"),
146
    0,
147
    sox_probe,
148
    sox_read_header,
149
    sox_read_packet,
150
    NULL,
151
    pcm_read_seek,
152
};