Mercurial > libavformat.hg
comparison westwood.c @ 1545:8811d543732e libavformat
Better VQA demuxer
author | kostya |
---|---|
date | Wed, 29 Nov 2006 05:42:59 +0000 |
parents | 0899bfe4105c |
children | 3b4019c023a3 |
comparison
equal
deleted
inserted
replaced
1544:49256f9ea0e9 | 1545:8811d543732e |
---|---|
42 #define FORM_TAG MKBETAG('F', 'O', 'R', 'M') | 42 #define FORM_TAG MKBETAG('F', 'O', 'R', 'M') |
43 #define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A') | 43 #define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A') |
44 #define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D') | 44 #define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D') |
45 #define FINF_TAG MKBETAG('F', 'I', 'N', 'F') | 45 #define FINF_TAG MKBETAG('F', 'I', 'N', 'F') |
46 #define SND0_TAG MKBETAG('S', 'N', 'D', '0') | 46 #define SND0_TAG MKBETAG('S', 'N', 'D', '0') |
47 #define SND1_TAG MKBETAG('S', 'N', 'D', '1') | |
47 #define SND2_TAG MKBETAG('S', 'N', 'D', '2') | 48 #define SND2_TAG MKBETAG('S', 'N', 'D', '2') |
48 #define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R') | 49 #define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R') |
49 | 50 |
50 /* don't know what these tags are for, but acknowledge their existence */ | 51 /* don't know what these tags are for, but acknowledge their existence */ |
51 #define CINF_TAG MKBETAG('C', 'I', 'N', 'F') | 52 #define CINF_TAG MKBETAG('C', 'I', 'N', 'F') |
52 #define CINH_TAG MKBETAG('C', 'I', 'N', 'H') | 53 #define CINH_TAG MKBETAG('C', 'I', 'N', 'H') |
53 #define CIND_TAG MKBETAG('C', 'I', 'N', 'D') | 54 #define CIND_TAG MKBETAG('C', 'I', 'N', 'D') |
54 #define PINF_TAG MKBETAG('P', 'I', 'N', 'F') | 55 #define PINF_TAG MKBETAG('P', 'I', 'N', 'F') |
55 #define PINH_TAG MKBETAG('P', 'I', 'N', 'H') | 56 #define PINH_TAG MKBETAG('P', 'I', 'N', 'H') |
56 #define PIND_TAG MKBETAG('P', 'I', 'N', 'D') | 57 #define PIND_TAG MKBETAG('P', 'I', 'N', 'D') |
58 #define CMDS_TAG MKBETAG('C', 'M', 'D', 'S') | |
57 | 59 |
58 #define VQA_HEADER_SIZE 0x2A | 60 #define VQA_HEADER_SIZE 0x2A |
59 #define VQA_FRAMERATE 15 | 61 #define VQA_FRAMERATE 15 |
60 #define VQA_VIDEO_PTS_INC (90000 / VQA_FRAMERATE) | 62 #define VQA_VIDEO_PTS_INC (90000 / VQA_FRAMERATE) |
61 #define VQA_PREAMBLE_SIZE 8 | 63 #define VQA_PREAMBLE_SIZE 8 |
241 return AVERROR_IO; | 243 return AVERROR_IO; |
242 } | 244 } |
243 st->codec->width = LE_16(&header[6]); | 245 st->codec->width = LE_16(&header[6]); |
244 st->codec->height = LE_16(&header[8]); | 246 st->codec->height = LE_16(&header[8]); |
245 | 247 |
246 /* initialize the audio decoder stream is sample rate is non-zero */ | 248 st->codec->time_base.num = 1; |
247 if (LE_16(&header[24])) { | 249 st->codec->time_base.den = VQA_FRAMERATE; |
250 | |
251 /* initialize the audio decoder stream for VQA v1 or nonzero samplerate */ | |
252 if (LE_16(&header[24]) || (LE_16(&header[0]) == 1)) { | |
248 st = av_new_stream(s, 0); | 253 st = av_new_stream(s, 0); |
249 if (!st) | 254 if (!st) |
250 return AVERROR_NOMEM; | 255 return AVERROR_NOMEM; |
251 av_set_pts_info(st, 33, 1, 90000); | 256 av_set_pts_info(st, 33, 1, 90000); |
252 st->codec->codec_type = CODEC_TYPE_AUDIO; | 257 st->codec->codec_type = CODEC_TYPE_AUDIO; |
253 st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; | 258 if (LE_16(&header[0]) == 1) |
259 st->codec->codec_id = CODEC_ID_WESTWOOD_SND1; | |
260 else | |
261 st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS; | |
254 st->codec->codec_tag = 0; /* no tag */ | 262 st->codec->codec_tag = 0; /* no tag */ |
255 st->codec->sample_rate = LE_16(&header[24]); | 263 st->codec->sample_rate = LE_16(&header[24]); |
264 if (!st->codec->sample_rate) | |
265 st->codec->sample_rate = 22050; | |
256 st->codec->channels = header[26]; | 266 st->codec->channels = header[26]; |
267 if (!st->codec->channels) | |
268 st->codec->channels = 1; | |
257 st->codec->bits_per_sample = 16; | 269 st->codec->bits_per_sample = 16; |
258 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * | 270 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * |
259 st->codec->bits_per_sample / 4; | 271 st->codec->bits_per_sample / 4; |
260 st->codec->block_align = st->codec->channels * st->codec->bits_per_sample; | 272 st->codec->block_align = st->codec->channels * st->codec->bits_per_sample; |
261 | 273 |
282 case CIND_TAG: | 294 case CIND_TAG: |
283 case PINF_TAG: | 295 case PINF_TAG: |
284 case PINH_TAG: | 296 case PINH_TAG: |
285 case PIND_TAG: | 297 case PIND_TAG: |
286 case FINF_TAG: | 298 case FINF_TAG: |
299 case CMDS_TAG: | |
287 break; | 300 break; |
288 | 301 |
289 default: | 302 default: |
290 av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n", | 303 av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n", |
291 scratch[0], scratch[1], | 304 scratch[0], scratch[1], |
304 static int wsvqa_read_packet(AVFormatContext *s, | 317 static int wsvqa_read_packet(AVFormatContext *s, |
305 AVPacket *pkt) | 318 AVPacket *pkt) |
306 { | 319 { |
307 WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data; | 320 WsVqaDemuxContext *wsvqa = (WsVqaDemuxContext *)s->priv_data; |
308 ByteIOContext *pb = &s->pb; | 321 ByteIOContext *pb = &s->pb; |
309 int ret = 0; | 322 int ret = -1; |
310 unsigned char preamble[VQA_PREAMBLE_SIZE]; | 323 unsigned char preamble[VQA_PREAMBLE_SIZE]; |
311 unsigned int chunk_type; | 324 unsigned int chunk_type; |
312 unsigned int chunk_size; | 325 unsigned int chunk_size; |
313 int skip_byte; | 326 int skip_byte; |
314 | 327 |
315 if (get_buffer(pb, preamble, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) | 328 while (get_buffer(pb, preamble, VQA_PREAMBLE_SIZE) == VQA_PREAMBLE_SIZE) { |
316 return AVERROR_IO; | 329 chunk_type = BE_32(&preamble[0]); |
317 | 330 chunk_size = BE_32(&preamble[4]); |
318 chunk_type = BE_32(&preamble[0]); | 331 skip_byte = chunk_size & 0x01; |
319 chunk_size = BE_32(&preamble[4]); | 332 |
320 skip_byte = chunk_size & 0x01; | 333 if ((chunk_type == SND1_TAG) || (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) { |
321 | 334 |
322 if ((chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) { | 335 if (av_new_packet(pkt, chunk_size)) |
323 | 336 return AVERROR_IO; |
324 av_get_packet(pb, pkt, chunk_size); | 337 ret = get_buffer(pb, pkt->data, chunk_size); |
325 if (ret != chunk_size) { | 338 if (ret != chunk_size) { |
326 ret = AVERROR_IO; | 339 av_free_packet(pkt); |
340 return AVERROR_IO; | |
341 } | |
342 | |
343 if (chunk_type == SND2_TAG) { | |
344 pkt->stream_index = wsvqa->audio_stream_index; | |
345 | |
346 pkt->pts = 90000; | |
347 pkt->pts *= wsvqa->audio_frame_counter; | |
348 pkt->pts /= wsvqa->audio_samplerate; | |
349 | |
350 /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ | |
351 wsvqa->audio_frame_counter += (chunk_size * 2) / wsvqa->audio_channels; | |
352 } else if(chunk_type == SND1_TAG) { | |
353 pkt->stream_index = wsvqa->audio_stream_index; | |
354 | |
355 pkt->pts = 90000; | |
356 pkt->pts *= wsvqa->audio_frame_counter; | |
357 pkt->pts /= wsvqa->audio_samplerate; | |
358 | |
359 /* unpacked size is stored in header */ | |
360 wsvqa->audio_frame_counter += LE_16(pkt->data) / wsvqa->audio_channels; | |
361 } else { | |
362 pkt->stream_index = wsvqa->video_stream_index; | |
363 pkt->pts = wsvqa->video_pts; | |
364 wsvqa->video_pts += VQA_VIDEO_PTS_INC; | |
365 } | |
366 /* stay on 16-bit alignment */ | |
367 if (skip_byte) | |
368 url_fseek(pb, 1, SEEK_CUR); | |
369 | |
370 return ret; | |
371 } else { | |
372 switch(chunk_type){ | |
373 case CMDS_TAG: | |
374 case SND0_TAG: | |
375 break; | |
376 default: | |
377 av_log(s, AV_LOG_INFO, "Skipping unknown chunk 0x%08X\n", chunk_type); | |
378 } | |
379 url_fseek(pb, chunk_size + skip_byte, SEEK_CUR); | |
327 } | 380 } |
328 | 381 } |
329 if (chunk_type == SND2_TAG) { | |
330 pkt->stream_index = wsvqa->audio_stream_index; | |
331 | |
332 pkt->pts = 90000; | |
333 pkt->pts *= wsvqa->audio_frame_counter; | |
334 pkt->pts /= wsvqa->audio_samplerate; | |
335 | |
336 /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ | |
337 wsvqa->audio_frame_counter += (chunk_size * 2) / | |
338 wsvqa->audio_channels; | |
339 } else { | |
340 pkt->stream_index = wsvqa->video_stream_index; | |
341 pkt->pts = wsvqa->video_pts; | |
342 wsvqa->video_pts += VQA_VIDEO_PTS_INC; | |
343 } | |
344 | |
345 } else | |
346 return AVERROR_INVALIDDATA; | |
347 | |
348 /* stay on 16-bit alignment */ | |
349 if (skip_byte) | |
350 url_fseek(pb, 1, SEEK_CUR); | |
351 | 382 |
352 return ret; | 383 return ret; |
353 } | 384 } |
354 | 385 |
355 static int wsvqa_read_close(AVFormatContext *s) | 386 static int wsvqa_read_close(AVFormatContext *s) |