Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
/*
2
 * AST demuxer
3
 * Copyright (c) 2012 Paul B Mahol
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
 
22
#include "libavutil/channel_layout.h"
23
#include "libavutil/intreadwrite.h"
24
#include "avformat.h"
25
#include "internal.h"
26
#include "ast.h"
27
 
28
static int ast_probe(AVProbeData *p)
29
{
30
    if (AV_RL32(p->buf) == MKTAG('S','T','R','M') &&
31
        AV_RB16(p->buf + 10) &&
32
        AV_RB16(p->buf + 12) &&
33
        AV_RB32(p->buf + 16))
34
        return AVPROBE_SCORE_MAX / 3 * 2;
35
    return 0;
36
}
37
 
38
static int ast_read_header(AVFormatContext *s)
39
{
40
    int depth;
41
    AVStream *st;
42
 
43
    st = avformat_new_stream(s, NULL);
44
    if (!st)
45
        return AVERROR(ENOMEM);
46
 
47
    avio_skip(s->pb, 8);
48
    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
49
    st->codec->codec_id   = ff_codec_get_id(ff_codec_ast_tags, avio_rb16(s->pb));
50
 
51
    depth = avio_rb16(s->pb);
52
    if (depth != 16) {
53
        avpriv_request_sample(s, "depth %d", depth);
54
        return AVERROR_INVALIDDATA;
55
    }
56
 
57
    st->codec->channels = avio_rb16(s->pb);
58
    if (!st->codec->channels)
59
        return AVERROR_INVALIDDATA;
60
 
61
    if (st->codec->channels == 2)
62
        st->codec->channel_layout = AV_CH_LAYOUT_STEREO;
63
    else if (st->codec->channels == 4)
64
        st->codec->channel_layout = AV_CH_LAYOUT_4POINT0;
65
 
66
    avio_skip(s->pb, 2);
67
    st->codec->sample_rate = avio_rb32(s->pb);
68
    if (st->codec->sample_rate <= 0)
69
        return AVERROR_INVALIDDATA;
70
    st->start_time         = 0;
71
    st->duration           = avio_rb32(s->pb);
72
    avio_skip(s->pb, 40);
73
    avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
74
 
75
    return 0;
76
}
77
 
78
static int ast_read_packet(AVFormatContext *s, AVPacket *pkt)
79
{
80
    uint32_t type, size;
81
    int64_t pos;
82
    int ret;
83
 
84
    if (url_feof(s->pb))
85
        return AVERROR_EOF;
86
 
87
    pos  = avio_tell(s->pb);
88
    type = avio_rl32(s->pb);
89
    size = avio_rb32(s->pb);
90
    if (size > INT_MAX / s->streams[0]->codec->channels)
91
        return AVERROR_INVALIDDATA;
92
 
93
    size *= s->streams[0]->codec->channels;
94
    if ((ret = avio_skip(s->pb, 24)) < 0) // padding
95
        return ret;
96
 
97
    if (type == MKTAG('B','L','C','K')) {
98
        ret = av_get_packet(s->pb, pkt, size);
99
        pkt->stream_index = 0;
100
        pkt->pos = pos;
101
    } else {
102
        av_log(s, AV_LOG_ERROR, "unknown chunk %x\n", type);
103
        avio_skip(s->pb, size);
104
        ret = AVERROR_INVALIDDATA;
105
    }
106
 
107
    return ret;
108
}
109
 
110
AVInputFormat ff_ast_demuxer = {
111
    .name           = "ast",
112
    .long_name      = NULL_IF_CONFIG_SMALL("AST (Audio Stream)"),
113
    .read_probe     = ast_probe,
114
    .read_header    = ast_read_header,
115
    .read_packet    = ast_read_packet,
116
    .extensions     = "ast",
117
    .flags          = AVFMT_GENERIC_INDEX,
118
    .codec_tag      = (const AVCodecTag* const []){ff_codec_ast_tags, 0},
119
};