~ubuntu-branches/ubuntu/oneiric/libav/oneiric

« back to all changes in this revision

Viewing changes to libavformat/idroq.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2011-04-19 15:04:55 UTC
  • mfrom: (1.2.1 upstream)
  • mto: (1.3.4 sid)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20110419150455-c1nac6gjm3t2aa4n
Tags: 4:0.7~b1-1
* New upstream version
* bump SONAME and SHLIBS
* configure flags --disable-stripping was removed upstream
* the MAINTAINERS file was removed upstream
* remove patch disable-configuration-warning.patch
* drop avfilter confflags, it is enable by default in 0.7
* libfaad wrapper has been removed upstream
* also update the *contents* of the lintian overrides

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * id RoQ (.roq) File Demuxer
3
 
 * Copyright (c) 2003 The ffmpeg Project
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
 
/**
23
 
 * @file
24
 
 * id RoQ format file demuxer
25
 
 * by Mike Melanson (melanson@pcisys.net)
26
 
 * for more information on the .roq file format, visit:
27
 
 *   http://www.csse.monash.edu.au/~timf/
28
 
 */
29
 
 
30
 
#include "libavutil/intreadwrite.h"
31
 
#include "avformat.h"
32
 
 
33
 
#define RoQ_MAGIC_NUMBER 0x1084
34
 
#define RoQ_CHUNK_PREAMBLE_SIZE 8
35
 
#define RoQ_AUDIO_SAMPLE_RATE 22050
36
 
#define RoQ_CHUNKS_TO_SCAN 30
37
 
 
38
 
#define RoQ_INFO           0x1001
39
 
#define RoQ_QUAD_CODEBOOK  0x1002
40
 
#define RoQ_QUAD_VQ        0x1011
41
 
#define RoQ_SOUND_MONO     0x1020
42
 
#define RoQ_SOUND_STEREO   0x1021
43
 
 
44
 
typedef struct RoqDemuxContext {
45
 
 
46
 
    int width;
47
 
    int height;
48
 
    int audio_channels;
49
 
 
50
 
    int video_stream_index;
51
 
    int audio_stream_index;
52
 
 
53
 
    int64_t video_pts;
54
 
    unsigned int audio_frame_count;
55
 
 
56
 
} RoqDemuxContext;
57
 
 
58
 
static int roq_probe(AVProbeData *p)
59
 
{
60
 
    if ((AV_RL16(&p->buf[0]) != RoQ_MAGIC_NUMBER) ||
61
 
        (AV_RL32(&p->buf[2]) != 0xFFFFFFFF))
62
 
        return 0;
63
 
 
64
 
    return AVPROBE_SCORE_MAX;
65
 
}
66
 
 
67
 
static int roq_read_header(AVFormatContext *s,
68
 
                           AVFormatParameters *ap)
69
 
{
70
 
    RoqDemuxContext *roq = s->priv_data;
71
 
    ByteIOContext *pb = s->pb;
72
 
    int framerate;
73
 
    AVStream *st;
74
 
    unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
75
 
 
76
 
    /* get the main header */
77
 
    if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
78
 
        RoQ_CHUNK_PREAMBLE_SIZE)
79
 
        return AVERROR(EIO);
80
 
    framerate = AV_RL16(&preamble[6]);
81
 
 
82
 
    /* init private context parameters */
83
 
    roq->width = roq->height = roq->audio_channels = roq->video_pts =
84
 
    roq->audio_frame_count = 0;
85
 
    roq->audio_stream_index = -1;
86
 
 
87
 
    st = av_new_stream(s, 0);
88
 
    if (!st)
89
 
        return AVERROR(ENOMEM);
90
 
    av_set_pts_info(st, 63, 1, framerate);
91
 
    roq->video_stream_index = st->index;
92
 
    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
93
 
    st->codec->codec_id = CODEC_ID_ROQ;
94
 
    st->codec->codec_tag = 0;  /* no fourcc */
95
 
 
96
 
    return 0;
97
 
}
98
 
 
99
 
static int roq_read_packet(AVFormatContext *s,
100
 
                           AVPacket *pkt)
101
 
{
102
 
    RoqDemuxContext *roq = s->priv_data;
103
 
    ByteIOContext *pb = s->pb;
104
 
    int ret = 0;
105
 
    unsigned int chunk_size;
106
 
    unsigned int chunk_type;
107
 
    unsigned int codebook_size;
108
 
    unsigned char preamble[RoQ_CHUNK_PREAMBLE_SIZE];
109
 
    int packet_read = 0;
110
 
    int64_t codebook_offset;
111
 
 
112
 
    while (!packet_read) {
113
 
 
114
 
        if (url_feof(s->pb))
115
 
            return AVERROR(EIO);
116
 
 
117
 
        /* get the next chunk preamble */
118
 
        if ((ret = get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE)) !=
119
 
            RoQ_CHUNK_PREAMBLE_SIZE)
120
 
            return AVERROR(EIO);
121
 
 
122
 
        chunk_type = AV_RL16(&preamble[0]);
123
 
        chunk_size = AV_RL32(&preamble[2]);
124
 
        if(chunk_size > INT_MAX)
125
 
            return AVERROR_INVALIDDATA;
126
 
 
127
 
        switch (chunk_type) {
128
 
 
129
 
        case RoQ_INFO:
130
 
            if (!roq->width || !roq->height) {
131
 
                AVStream *st = s->streams[roq->video_stream_index];
132
 
                if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE)
133
 
                    return AVERROR(EIO);
134
 
                st->codec->width  = roq->width  = AV_RL16(preamble);
135
 
                st->codec->height = roq->height = AV_RL16(preamble + 2);
136
 
                break;
137
 
            }
138
 
            /* don't care about this chunk anymore */
139
 
            url_fseek(pb, RoQ_CHUNK_PREAMBLE_SIZE, SEEK_CUR);
140
 
            break;
141
 
 
142
 
        case RoQ_QUAD_CODEBOOK:
143
 
            /* packet needs to contain both this codebook and next VQ chunk */
144
 
            codebook_offset = url_ftell(pb) - RoQ_CHUNK_PREAMBLE_SIZE;
145
 
            codebook_size = chunk_size;
146
 
            url_fseek(pb, codebook_size, SEEK_CUR);
147
 
            if (get_buffer(pb, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
148
 
                RoQ_CHUNK_PREAMBLE_SIZE)
149
 
                return AVERROR(EIO);
150
 
            chunk_size = AV_RL32(&preamble[2]) + RoQ_CHUNK_PREAMBLE_SIZE * 2 +
151
 
                codebook_size;
152
 
 
153
 
            /* rewind */
154
 
            url_fseek(pb, codebook_offset, SEEK_SET);
155
 
 
156
 
            /* load up the packet */
157
 
            ret= av_get_packet(pb, pkt, chunk_size);
158
 
            if (ret != chunk_size)
159
 
                return AVERROR(EIO);
160
 
            pkt->stream_index = roq->video_stream_index;
161
 
            pkt->pts = roq->video_pts++;
162
 
 
163
 
            packet_read = 1;
164
 
            break;
165
 
 
166
 
        case RoQ_SOUND_MONO:
167
 
        case RoQ_SOUND_STEREO:
168
 
            if (roq->audio_stream_index == -1) {
169
 
                AVStream *st = av_new_stream(s, 1);
170
 
                if (!st)
171
 
                    return AVERROR(ENOMEM);
172
 
                av_set_pts_info(st, 32, 1, RoQ_AUDIO_SAMPLE_RATE);
173
 
                roq->audio_stream_index = st->index;
174
 
                st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
175
 
                st->codec->codec_id = CODEC_ID_ROQ_DPCM;
176
 
                st->codec->codec_tag = 0;  /* no tag */
177
 
                st->codec->channels = roq->audio_channels = chunk_type == RoQ_SOUND_STEREO ? 2 : 1;
178
 
                st->codec->sample_rate = RoQ_AUDIO_SAMPLE_RATE;
179
 
                st->codec->bits_per_coded_sample = 16;
180
 
                st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
181
 
                    st->codec->bits_per_coded_sample;
182
 
                st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
183
 
            }
184
 
        case RoQ_QUAD_VQ:
185
 
            /* load up the packet */
186
 
            if (av_new_packet(pkt, chunk_size + RoQ_CHUNK_PREAMBLE_SIZE))
187
 
                return AVERROR(EIO);
188
 
            /* copy over preamble */
189
 
            memcpy(pkt->data, preamble, RoQ_CHUNK_PREAMBLE_SIZE);
190
 
 
191
 
            if (chunk_type == RoQ_QUAD_VQ) {
192
 
                pkt->stream_index = roq->video_stream_index;
193
 
                pkt->pts = roq->video_pts++;
194
 
            } else {
195
 
                pkt->stream_index = roq->audio_stream_index;
196
 
                pkt->pts = roq->audio_frame_count;
197
 
                roq->audio_frame_count += (chunk_size / roq->audio_channels);
198
 
            }
199
 
 
200
 
            pkt->pos= url_ftell(pb);
201
 
            ret = get_buffer(pb, pkt->data + RoQ_CHUNK_PREAMBLE_SIZE,
202
 
                chunk_size);
203
 
            if (ret != chunk_size)
204
 
                ret = AVERROR(EIO);
205
 
 
206
 
            packet_read = 1;
207
 
            break;
208
 
 
209
 
        default:
210
 
            av_log(s, AV_LOG_ERROR, "  unknown RoQ chunk (%04X)\n", chunk_type);
211
 
            return AVERROR_INVALIDDATA;
212
 
            break;
213
 
        }
214
 
    }
215
 
 
216
 
    return ret;
217
 
}
218
 
 
219
 
AVInputFormat roq_demuxer = {
220
 
    "RoQ",
221
 
    NULL_IF_CONFIG_SMALL("id RoQ format"),
222
 
    sizeof(RoqDemuxContext),
223
 
    roq_probe,
224
 
    roq_read_header,
225
 
    roq_read_packet,
226
 
};