~ubuntu-branches/ubuntu/trusty/gst-libav1.0/trusty-proposed

« back to all changes in this revision

Viewing changes to gst-libs/ext/libav/libavformat/4xm.c

  • Committer: Package Import Robot
  • Author(s): Sebastian Dröge
  • Date: 2013-09-24 17:07:00 UTC
  • mfrom: (1.1.17) (7.1.9 experimental)
  • Revision ID: package-import@ubuntu.com-20130924170700-4dg62s3pwl0pdakz
Tags: 1.2.0-1
* New upstream stable release:
  + debian/control:
    - Build depend on GStreamer and gst-plugins-base >= 1.2.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
57
57
 
58
58
#define GET_LIST_HEADER() \
59
59
    fourcc_tag = avio_rl32(pb); \
60
 
    size = avio_rl32(pb); \
 
60
    size       = avio_rl32(pb); \
61
61
    if (fourcc_tag != LIST_TAG) \
62
62
        return AVERROR_INVALIDDATA; \
63
63
    fourcc_tag = avio_rl32(pb);
72
72
} AudioTrack;
73
73
 
74
74
typedef struct FourxmDemuxContext {
75
 
    int width;
76
 
    int height;
77
75
    int video_stream_index;
78
76
    int track_count;
79
77
    AudioTrack *tracks;
91
89
    return AVPROBE_SCORE_MAX;
92
90
}
93
91
 
94
 
static int fourxm_read_header(AVFormatContext *s,
95
 
                              AVFormatParameters *ap)
 
92
static int parse_vtrk(AVFormatContext *s,
 
93
                      FourxmDemuxContext *fourxm, uint8_t *buf, int size,
 
94
                      int left)
 
95
{
 
96
    AVStream *st;
 
97
    /* check that there is enough data */
 
98
    if (size != vtrk_SIZE || left < size + 8) {
 
99
        return AVERROR_INVALIDDATA;
 
100
    }
 
101
 
 
102
    /* allocate a new AVStream */
 
103
    st = avformat_new_stream(s, NULL);
 
104
    if (!st)
 
105
        return AVERROR(ENOMEM);
 
106
 
 
107
    avpriv_set_pts_info(st, 60, 1, fourxm->fps);
 
108
 
 
109
    fourxm->video_stream_index = st->index;
 
110
 
 
111
    st->codec->codec_type     = AVMEDIA_TYPE_VIDEO;
 
112
    st->codec->codec_id       = AV_CODEC_ID_4XM;
 
113
    st->codec->extradata_size = 4;
 
114
    st->codec->extradata      = av_malloc(4);
 
115
    AV_WL32(st->codec->extradata, AV_RL32(buf + 16));
 
116
    st->codec->width  = AV_RL32(buf + 36);
 
117
    st->codec->height = AV_RL32(buf + 40);
 
118
 
 
119
    return 0;
 
120
}
 
121
 
 
122
 
 
123
static int parse_strk(AVFormatContext *s,
 
124
                      FourxmDemuxContext *fourxm, uint8_t *buf, int size,
 
125
                      int left)
 
126
{
 
127
    AVStream *st;
 
128
    int track;
 
129
    /* check that there is enough data */
 
130
    if (size != strk_SIZE || left < size + 8)
 
131
        return AVERROR_INVALIDDATA;
 
132
 
 
133
    track = AV_RL32(buf + 8);
 
134
 
 
135
    if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) {
 
136
        av_log(s, AV_LOG_ERROR, "current_track too large\n");
 
137
        return AVERROR_INVALIDDATA;
 
138
    }
 
139
    if (track < 0)
 
140
        return AVERROR_INVALIDDATA;
 
141
    if (track + 1 > fourxm->track_count) {
 
142
        AudioTrack *tmp = av_realloc(fourxm->tracks,
 
143
                                     (track + 1) * sizeof(AudioTrack));
 
144
        if (!tmp)
 
145
            return AVERROR(ENOMEM);
 
146
        fourxm->tracks = tmp;
 
147
        memset(&fourxm->tracks[fourxm->track_count], 0,
 
148
               sizeof(AudioTrack) * (track + 1 - fourxm->track_count));
 
149
        fourxm->track_count = track + 1;
 
150
    }
 
151
    fourxm->tracks[track].adpcm       = AV_RL32(buf + 12);
 
152
    fourxm->tracks[track].channels    = AV_RL32(buf + 36);
 
153
    fourxm->tracks[track].sample_rate = AV_RL32(buf + 40);
 
154
    fourxm->tracks[track].bits        = AV_RL32(buf + 44);
 
155
    fourxm->tracks[track].audio_pts   = 0;
 
156
 
 
157
    if (fourxm->tracks[track].channels    <= 0 ||
 
158
        fourxm->tracks[track].sample_rate <= 0 ||
 
159
        fourxm->tracks[track].bits        <= 0) {
 
160
        av_log(s, AV_LOG_ERROR, "audio header invalid\n");
 
161
        return AVERROR_INVALIDDATA;
 
162
    }
 
163
    /* allocate a new AVStream */
 
164
    st = avformat_new_stream(s, NULL);
 
165
    if (!st)
 
166
        return AVERROR(ENOMEM);
 
167
 
 
168
    st->id = track;
 
169
    avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate);
 
170
 
 
171
    fourxm->tracks[track].stream_index = st->index;
 
172
 
 
173
    st->codec->codec_type            = AVMEDIA_TYPE_AUDIO;
 
174
    st->codec->codec_tag             = 0;
 
175
    st->codec->channels              = fourxm->tracks[track].channels;
 
176
    st->codec->sample_rate           = fourxm->tracks[track].sample_rate;
 
177
    st->codec->bits_per_coded_sample = fourxm->tracks[track].bits;
 
178
    st->codec->bit_rate              = st->codec->channels *
 
179
                                       st->codec->sample_rate *
 
180
                                       st->codec->bits_per_coded_sample;
 
181
    st->codec->block_align           = st->codec->channels *
 
182
                                       st->codec->bits_per_coded_sample;
 
183
 
 
184
    if (fourxm->tracks[track].adpcm){
 
185
        st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM;
 
186
    } else if (st->codec->bits_per_coded_sample == 8) {
 
187
        st->codec->codec_id = AV_CODEC_ID_PCM_U8;
 
188
    } else
 
189
        st->codec->codec_id = AV_CODEC_ID_PCM_S16LE;
 
190
 
 
191
    return 0;
 
192
}
 
193
 
 
194
static int fourxm_read_header(AVFormatContext *s)
96
195
{
97
196
    AVIOContext *pb = s->pb;
98
197
    unsigned int fourcc_tag;
101
200
    FourxmDemuxContext *fourxm = s->priv_data;
102
201
    unsigned char *header;
103
202
    int i, ret;
104
 
    AVStream *st;
105
203
 
106
204
    fourxm->track_count = 0;
107
 
    fourxm->tracks = NULL;
108
 
    fourxm->fps = 1.0;
 
205
    fourxm->tracks      = NULL;
 
206
    fourxm->fps         = 1.0;
109
207
 
110
208
    /* skip the first 3 32-bit numbers */
111
209
    avio_skip(pb, 12);
120
218
    header = av_malloc(header_size);
121
219
    if (!header)
122
220
        return AVERROR(ENOMEM);
123
 
    if (avio_read(pb, header, header_size) != header_size){
 
221
    if (avio_read(pb, header, header_size) != header_size) {
124
222
        av_free(header);
125
223
        return AVERROR(EIO);
126
224
    }
128
226
    /* take the lazy approach and search for any and all vtrk and strk chunks */
129
227
    for (i = 0; i < header_size - 8; i++) {
130
228
        fourcc_tag = AV_RL32(&header[i]);
131
 
        size = AV_RL32(&header[i + 4]);
 
229
        size       = AV_RL32(&header[i + 4]);
132
230
 
133
231
        if (fourcc_tag == std__TAG) {
 
232
            if (header_size - i < 16) {
 
233
                ret = AVERROR_INVALIDDATA;
 
234
                goto fail;
 
235
            }
134
236
            fourxm->fps = av_int2float(AV_RL32(&header[i + 12]));
135
237
        } else if (fourcc_tag == vtrk_TAG) {
136
 
            /* check that there is enough data */
137
 
            if (size != vtrk_SIZE) {
138
 
                ret= AVERROR_INVALIDDATA;
139
 
                goto fail;
140
 
            }
141
 
            fourxm->width  = AV_RL32(&header[i + 36]);
142
 
            fourxm->height = AV_RL32(&header[i + 40]);
143
 
 
144
 
            /* allocate a new AVStream */
145
 
            st = avformat_new_stream(s, NULL);
146
 
            if (!st){
147
 
                ret= AVERROR(ENOMEM);
148
 
                goto fail;
149
 
            }
150
 
            avpriv_set_pts_info(st, 60, 1, fourxm->fps);
151
 
 
152
 
            fourxm->video_stream_index = st->index;
153
 
 
154
 
            st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
155
 
            st->codec->codec_id = CODEC_ID_4XM;
156
 
            st->codec->extradata_size = 4;
157
 
            st->codec->extradata = av_malloc(4);
158
 
            AV_WL32(st->codec->extradata, AV_RL32(&header[i + 16]));
159
 
            st->codec->width  = fourxm->width;
160
 
            st->codec->height = fourxm->height;
 
238
            if ((ret = parse_vtrk(s, fourxm, header + i, size,
 
239
                                  header_size - i)) < 0)
 
240
                goto fail;
161
241
 
162
242
            i += 8 + size;
163
243
        } else if (fourcc_tag == strk_TAG) {
164
 
            int current_track;
165
 
            /* check that there is enough data */
166
 
            if (size != strk_SIZE) {
167
 
                ret= AVERROR_INVALIDDATA;
168
 
                goto fail;
169
 
            }
170
 
            current_track = AV_RL32(&header[i + 8]);
171
 
            if((unsigned)current_track >= UINT_MAX / sizeof(AudioTrack) - 1){
172
 
                av_log(s, AV_LOG_ERROR, "current_track too large\n");
173
 
                ret= -1;
174
 
                goto fail;
175
 
            }
176
 
            if (current_track + 1 > fourxm->track_count) {
177
 
                fourxm->tracks = av_realloc(fourxm->tracks,
178
 
                    (current_track + 1) * sizeof(AudioTrack));
179
 
                if (!fourxm->tracks) {
180
 
                    ret = AVERROR(ENOMEM);
181
 
                    goto fail;
182
 
                }
183
 
                memset(&fourxm->tracks[fourxm->track_count], 0,
184
 
                       sizeof(AudioTrack) * (current_track + 1 - fourxm->track_count));
185
 
                fourxm->track_count = current_track + 1;
186
 
            }
187
 
            fourxm->tracks[current_track].adpcm       = AV_RL32(&header[i + 12]);
188
 
            fourxm->tracks[current_track].channels    = AV_RL32(&header[i + 36]);
189
 
            fourxm->tracks[current_track].sample_rate = AV_RL32(&header[i + 40]);
190
 
            fourxm->tracks[current_track].bits        = AV_RL32(&header[i + 44]);
191
 
            fourxm->tracks[current_track].audio_pts   = 0;
192
 
            if(   fourxm->tracks[current_track].channels    <= 0
193
 
               || fourxm->tracks[current_track].sample_rate <= 0
194
 
               || fourxm->tracks[current_track].bits        <  0){
195
 
                av_log(s, AV_LOG_ERROR, "audio header invalid\n");
196
 
                ret= -1;
197
 
                goto fail;
198
 
            }
 
244
            if ((ret = parse_strk(s, fourxm, header + i, size,
 
245
                                  header_size - i)) < 0)
 
246
                goto fail;
 
247
 
199
248
            i += 8 + size;
200
 
 
201
 
            /* allocate a new AVStream */
202
 
            st = avformat_new_stream(s, NULL);
203
 
            if (!st){
204
 
                ret= AVERROR(ENOMEM);
205
 
                goto fail;
206
 
            }
207
 
 
208
 
            st->id = current_track;
209
 
            avpriv_set_pts_info(st, 60, 1, fourxm->tracks[current_track].sample_rate);
210
 
 
211
 
            fourxm->tracks[current_track].stream_index = st->index;
212
 
 
213
 
            st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
214
 
            st->codec->codec_tag = 0;
215
 
            st->codec->channels              = fourxm->tracks[current_track].channels;
216
 
            st->codec->sample_rate           = fourxm->tracks[current_track].sample_rate;
217
 
            st->codec->bits_per_coded_sample = fourxm->tracks[current_track].bits;
218
 
            st->codec->bit_rate              = st->codec->channels * st->codec->sample_rate *
219
 
                st->codec->bits_per_coded_sample;
220
 
            st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
221
 
            if (fourxm->tracks[current_track].adpcm){
222
 
                st->codec->codec_id = CODEC_ID_ADPCM_4XM;
223
 
            }else if (st->codec->bits_per_coded_sample == 8){
224
 
                st->codec->codec_id = CODEC_ID_PCM_U8;
225
 
            }else
226
 
                st->codec->codec_id = CODEC_ID_PCM_S16LE;
227
249
        }
228
250
    }
229
251
 
230
252
    /* skip over the LIST-MOVI chunk (which is where the stream should be */
231
253
    GET_LIST_HEADER();
232
 
    if (fourcc_tag != MOVI_TAG){
233
 
        ret= AVERROR_INVALIDDATA;
 
254
    if (fourcc_tag != MOVI_TAG) {
 
255
        ret = AVERROR_INVALIDDATA;
234
256
        goto fail;
235
257
    }
236
258
 
249
271
                              AVPacket *pkt)
250
272
{
251
273
    FourxmDemuxContext *fourxm = s->priv_data;
252
 
    AVIOContext *pb = s->pb;
 
274
    AVIOContext *pb            = s->pb;
253
275
    unsigned int fourcc_tag;
254
276
    unsigned int size;
255
277
    int ret = 0;
259
281
    int audio_frame_count;
260
282
 
261
283
    while (!packet_read) {
262
 
 
263
284
        if ((ret = avio_read(s->pb, header, 8)) < 0)
264
285
            return ret;
265
286
        fourcc_tag = AV_RL32(&header[0]);
266
 
        size = AV_RL32(&header[4]);
 
287
        size       = AV_RL32(&header[4]);
267
288
        if (pb->eof_reached)
268
289
            return AVERROR(EIO);
269
290
        switch (fourcc_tag) {
270
 
 
271
291
        case LIST_TAG:
272
292
            /* this is a good time to bump the video pts */
273
 
            fourxm->video_pts ++;
 
293
            fourxm->video_pts++;
274
294
 
275
295
            /* skip the LIST-* tag and move on to the next fourcc */
276
296
            avio_rl32(pb);
287
307
            if (size + 8 < size || av_new_packet(pkt, size + 8))
288
308
                return AVERROR(EIO);
289
309
            pkt->stream_index = fourxm->video_stream_index;
290
 
            pkt->pts = fourxm->video_pts;
291
 
            pkt->pos = avio_tell(s->pb);
 
310
            pkt->pts          = fourxm->video_pts;
 
311
            pkt->pos          = avio_tell(s->pb);
292
312
            memcpy(pkt->data, header, 8);
293
313
            ret = avio_read(s->pb, &pkt->data[8], size);
294
314
 
295
 
            if (ret < 0){
 
315
            if (ret < 0) {
296
316
                av_free_packet(pkt);
297
 
            }else
 
317
            } else
298
318
                packet_read = 1;
299
319
            break;
300
320
 
301
321
        case snd__TAG:
302
322
            track_number = avio_rl32(pb);
303
323
            avio_skip(pb, 4);
304
 
            size-=8;
 
324
            size -= 8;
305
325
 
306
 
            if (track_number < fourxm->track_count && fourxm->tracks[track_number].channels>0) {
307
 
                ret= av_get_packet(s->pb, pkt, size);
308
 
                if(ret<0)
 
326
            if (track_number < fourxm->track_count &&
 
327
                fourxm->tracks[track_number].channels > 0) {
 
328
                ret = av_get_packet(s->pb, pkt, size);
 
329
                if (ret < 0)
309
330
                    return AVERROR(EIO);
310
331
                pkt->stream_index =
311
332
                    fourxm->tracks[track_number].stream_index;
312
 
                pkt->pts = fourxm->tracks[track_number].audio_pts;
 
333
                pkt->pts    = fourxm->tracks[track_number].audio_pts;
313
334
                packet_read = 1;
314
335
 
315
336
                /* pts accounting */
316
337
                audio_frame_count = size;
317
338
                if (fourxm->tracks[track_number].adpcm)
318
 
                    audio_frame_count -=
319
 
                        2 * (fourxm->tracks[track_number].channels);
320
 
                audio_frame_count /=
321
 
                      fourxm->tracks[track_number].channels;
322
 
                if (fourxm->tracks[track_number].adpcm){
 
339
                    audio_frame_count -= 2 * (fourxm->tracks[track_number].channels);
 
340
                audio_frame_count /= fourxm->tracks[track_number].channels;
 
341
                if (fourxm->tracks[track_number].adpcm) {
323
342
                    audio_frame_count *= 2;
324
 
                }else
 
343
                } else
325
344
                    audio_frame_count /=
326
 
                    (fourxm->tracks[track_number].bits / 8);
 
345
                        (fourxm->tracks[track_number].bits / 8);
327
346
                fourxm->tracks[track_number].audio_pts += audio_frame_count;
328
 
 
329
347
            } else {
330
348
                avio_skip(pb, size);
331
349
            }
350
368
 
351
369
AVInputFormat ff_fourxm_demuxer = {
352
370
    .name           = "4xm",
353
 
    .long_name      = NULL_IF_CONFIG_SMALL("4X Technologies format"),
 
371
    .long_name      = NULL_IF_CONFIG_SMALL("4X Technologies"),
354
372
    .priv_data_size = sizeof(FourxmDemuxContext),
355
373
    .read_probe     = fourxm_probe,
356
374
    .read_header    = fourxm_read_header,