Statistics
| Branch: | Revision:

ffmpeg / libavformat / soxdec.c @ e356fc57

History | View | Annotate | Download (4.57 KB)

1
/*
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
 * @file
28
 * @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
#include "pcm.h"
35
#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
    AVIOContext *pb = s->pb;
48
    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
    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
57

    
58
    if (avio_rl32(pb) == SOX_TAG) {
59
        st->codec->codec_id = CODEC_ID_PCM_S32LE;
60
        header_size         = avio_rl32(pb);
61
        avio_seek(pb, 8, SEEK_CUR); /* sample count */
62
        sample_rate         = av_int2dbl(avio_rl64(pb));
63
        st->codec->channels = avio_rl32(pb);
64
        comment_size        = avio_rl32(pb);
65
    } else {
66
        st->codec->codec_id = CODEC_ID_PCM_S32BE;
67
        header_size         = avio_rb32(pb);
68
        avio_seek(pb, 8, SEEK_CUR); /* sample count */
69
        sample_rate         = av_int2dbl(avio_rb64(pb));
70
        st->codec->channels = avio_rb32(pb);
71
        comment_size        = avio_rb32(pb);
72
    }
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
    if (comment_size && comment_size < UINT_MAX) {
97
        char *comment = av_malloc(comment_size+1);
98
        if (avio_read(pb, comment, comment_size) != comment_size) {
99
            av_freep(&comment);
100
            return AVERROR(EIO);
101
        }
102
        comment[comment_size] = 0;
103

    
104
        av_metadata_set2(&s->metadata, "comment", comment,
105
                               AV_METADATA_DONT_STRDUP_VAL);
106
    }
107

    
108
    avio_seek(pb, header_size - SOX_FIXED_HDR - comment_size, SEEK_CUR);
109

    
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
    st->codec->block_align           = st->codec->bits_per_coded_sample *
116
                                       st->codec->channels / 8;
117

    
118
    av_set_pts_info(st, 64, 1, st->codec->sample_rate);
119

    
120
    return 0;
121
}
122

    
123
#define SOX_SAMPLES 1024
124

    
125
static int sox_read_packet(AVFormatContext *s,
126
                           AVPacket *pkt)
127
{
128
    int ret, size;
129

    
130
    if (url_feof(s->pb))
131
        return AVERROR_EOF;
132

    
133
    size = SOX_SAMPLES*s->streams[0]->codec->block_align;
134
    ret = av_get_packet(s->pb, pkt, size);
135
    if (ret < 0)
136
        return AVERROR(EIO);
137
    pkt->stream_index = 0;
138
    pkt->size = ret;
139

    
140
    return 0;
141
}
142

    
143
AVInputFormat ff_sox_demuxer = {
144
    "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
};