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 | };>=> |