Originally committed as revision 6672 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -61,6 +61,7 @@ version <next> | |||
| - WavPack lossless audio decoder | |||
| - Targa (.TGA) picture decoder | |||
| - Delphine Software .cin demuxer/audio and video decoder | |||
| - Tiertex .seq demuxer/video decoder | |||
| version 0.4.9-pre1: | |||
| @@ -740,6 +740,8 @@ library: | |||
| @tab Multimedia format used by Delphine Software games. | |||
| @item MXF @tab @tab X | |||
| @tab Material eXchange Format SMPTE 377M, used by D-Cinema, broadcast industry. | |||
| @item SEQ @tab @tab X | |||
| @tab Tiertex .seq files used in the DOS CDROM version of the game Flashback. | |||
| @end multitable | |||
| @code{X} means that encoding (resp. decoding) is supported. | |||
| @@ -843,6 +845,7 @@ following image formats are supported: | |||
| @item KMVC @tab @tab X @tab Codec used in Worms games. | |||
| @item VMware Video @tab @tab X @tab Codec used in videos captured by VMware. | |||
| @item Cin Video @tab @tab X @tab Codec used in Delphine Software games. | |||
| @item Tiertex Seq Video @tab @tab X @tab Codec used in DOS CDROM FlashBack game. | |||
| @end multitable | |||
| @code{X} means that encoding (resp. decoding) is supported. | |||
| @@ -146,6 +146,7 @@ OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o | |||
| OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o | |||
| OBJS-$(CONFIG_VMDVIDEO_DECODER) += vmdav.o | |||
| OBJS-$(CONFIG_VMNC_DECODER) += vmnc.o | |||
| OBJS-$(CONFIG_TIERTEXSEQVIDEO_DECODER) += tiertexseqv.o | |||
| OBJS-$(CONFIG_VORBIS_DECODER) += vorbis.o vorbis_data.o | |||
| OBJS-$(CONFIG_VORBIS_ENCODER) += vorbis_enc.o vorbis_data.o | |||
| OBJS-$(CONFIG_VP3_DECODER) += vp3.o | |||
| @@ -554,6 +554,9 @@ void avcodec_register_all(void) | |||
| #ifdef CONFIG_DSICINAUDIO_DECODER | |||
| register_avcodec(&dsicinaudio_decoder); | |||
| #endif //CONFIG_DSICINAUDIO_DECODER | |||
| #ifdef CONFIG_TIERTEXSEQVIDEO_DECODER | |||
| register_avcodec(&tiertexseqvideo_decoder); | |||
| #endif //CONFIG_TIERTEXSEQVIDEO_DECODER | |||
| #if defined(CONFIG_AMR_NB) || defined(CONFIG_AMR_NB_FIXED) | |||
| #ifdef CONFIG_AMR_NB_DECODER | |||
| @@ -37,8 +37,8 @@ extern "C" { | |||
| #define AV_STRINGIFY(s) AV_TOSTRING(s) | |||
| #define AV_TOSTRING(s) #s | |||
| #define LIBAVCODEC_VERSION_INT ((51<<16)+(18<<8)+0) | |||
| #define LIBAVCODEC_VERSION 51.18.0 | |||
| #define LIBAVCODEC_VERSION_INT ((51<<16)+(19<<8)+0) | |||
| #define LIBAVCODEC_VERSION 51.19.0 | |||
| #define LIBAVCODEC_BUILD LIBAVCODEC_VERSION_INT | |||
| #define LIBAVCODEC_IDENT "Lavc" AV_STRINGIFY(LIBAVCODEC_VERSION) | |||
| @@ -146,6 +146,7 @@ enum CodecID { | |||
| CODEC_ID_VP6F, | |||
| CODEC_ID_TARGA, | |||
| CODEC_ID_DSICINVIDEO, | |||
| CODEC_ID_TIERTEXSEQVIDEO, | |||
| /* various pcm "codecs" */ | |||
| CODEC_ID_PCM_S16LE= 0x10000, | |||
| @@ -2298,6 +2299,7 @@ extern AVCodec wavpack_decoder; | |||
| extern AVCodec targa_decoder; | |||
| extern AVCodec dsicinvideo_decoder; | |||
| extern AVCodec dsicinaudio_decoder; | |||
| extern AVCodec tiertexseqvideo_decoder; | |||
| /* pcm codecs */ | |||
| #define PCM_CODEC(id, name) \ | |||
| @@ -0,0 +1,232 @@ | |||
| /* | |||
| * Tiertex Limited SEQ Video Decoder | |||
| * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| /** | |||
| * @file tiertexseqv.c | |||
| * Tiertex Limited SEQ video decoder | |||
| */ | |||
| #include "avcodec.h" | |||
| #include "common.h" | |||
| #define ALT_BITSTREAM_READER_LE | |||
| #include "bitstream.h" | |||
| typedef struct SeqVideoContext { | |||
| AVCodecContext *avctx; | |||
| AVFrame frame; | |||
| unsigned int palette[256]; | |||
| unsigned char block[8 * 8]; | |||
| } SeqVideoContext; | |||
| static unsigned char *seq_unpack_rle_block(unsigned char *src, unsigned char *dst, int dst_size) | |||
| { | |||
| int i, len, sz; | |||
| GetBitContext gb; | |||
| int code_table[64]; | |||
| /* get the rle codes (at most 64 bytes) */ | |||
| init_get_bits(&gb, src, 64 * 8); | |||
| for (i = 0, sz = 0; i < 64 && sz < dst_size; i++) { | |||
| code_table[i] = get_sbits(&gb, 4); | |||
| sz += FFABS(code_table[i]); | |||
| } | |||
| src += (get_bits_count(&gb) + 7) / 8; | |||
| /* do the rle unpacking */ | |||
| for (i = 0; i < 64 && dst_size > 0; i++) { | |||
| len = code_table[i]; | |||
| if (len < 0) { | |||
| len = -len; | |||
| memset(dst, *src++, FFMIN(len, dst_size)); | |||
| } else { | |||
| memcpy(dst, src, FFMIN(len, dst_size)); | |||
| src += len; | |||
| } | |||
| dst += len; | |||
| dst_size -= len; | |||
| } | |||
| return src; | |||
| } | |||
| static unsigned char *seq_decode_op1(SeqVideoContext *seq, unsigned char *src, unsigned char *dst) | |||
| { | |||
| unsigned char *color_table; | |||
| int b, i, len, bits; | |||
| GetBitContext gb; | |||
| len = *src++; | |||
| if (len & 0x80) { | |||
| switch (len & 3) { | |||
| case 1: | |||
| src = seq_unpack_rle_block(src, seq->block, sizeof(seq->block)); | |||
| for (b = 0; b < 8; b++) { | |||
| memcpy(dst, &seq->block[b * 8], 8); | |||
| dst += seq->frame.linesize[0]; | |||
| } | |||
| break; | |||
| case 2: | |||
| src = seq_unpack_rle_block(src, seq->block, sizeof(seq->block)); | |||
| for (i = 0; i < 8; i++) { | |||
| for (b = 0; b < 8; b++) | |||
| dst[b * seq->frame.linesize[0]] = seq->block[i * 8 + b]; | |||
| ++dst; | |||
| } | |||
| break; | |||
| } | |||
| } else { | |||
| color_table = src; | |||
| src += len; | |||
| bits = ff_log2_tab[len - 1] + 1; | |||
| init_get_bits(&gb, src, bits * 8 * 8); src += bits * 8; | |||
| for (b = 0; b < 8; b++) { | |||
| for (i = 0; i < 8; i++) | |||
| dst[i] = color_table[get_bits(&gb, bits)]; | |||
| dst += seq->frame.linesize[0]; | |||
| } | |||
| } | |||
| return src; | |||
| } | |||
| static unsigned char *seq_decode_op2(SeqVideoContext *seq, unsigned char *src, unsigned char *dst) | |||
| { | |||
| int i; | |||
| for (i = 0; i < 8; i++) { | |||
| memcpy(dst, src, 8); | |||
| src += 8; | |||
| dst += seq->frame.linesize[0]; | |||
| } | |||
| return src; | |||
| } | |||
| static unsigned char *seq_decode_op3(SeqVideoContext *seq, unsigned char *src, unsigned char *dst) | |||
| { | |||
| int pos, offset; | |||
| do { | |||
| pos = *src++; | |||
| offset = ((pos >> 3) & 7) * seq->frame.linesize[0] + (pos & 7); | |||
| dst[offset] = *src++; | |||
| } while (!(pos & 0x80)); | |||
| return src; | |||
| } | |||
| static void seqvideo_decode(SeqVideoContext *seq, unsigned char *data, int data_size) | |||
| { | |||
| GetBitContext gb; | |||
| int flags, i, j, x, y, op; | |||
| unsigned char c[3]; | |||
| unsigned char *dst; | |||
| flags = *data++; | |||
| if (flags & 1) { | |||
| for (i = 0; i < 256; i++) { | |||
| for (j = 0; j < 3; j++, data++) | |||
| c[j] = (*data << 2) | (*data >> 4); | |||
| seq->palette[i] = (c[0] << 16) | (c[1] << 8) | c[2]; | |||
| } | |||
| memcpy(seq->frame.data[1], seq->palette, sizeof(seq->palette)); | |||
| seq->frame.palette_has_changed = 1; | |||
| } | |||
| if (flags & 2) { | |||
| init_get_bits(&gb, data, 128 * 8); data += 128; | |||
| for (y = 0; y < 128; y += 8) | |||
| for (x = 0; x < 256; x += 8) { | |||
| dst = &seq->frame.data[0][y * seq->frame.linesize[0] + x]; | |||
| op = get_bits(&gb, 2); | |||
| switch (op) { | |||
| case 1: | |||
| data = seq_decode_op1(seq, data, dst); | |||
| break; | |||
| case 2: | |||
| data = seq_decode_op2(seq, data, dst); | |||
| break; | |||
| case 3: | |||
| data = seq_decode_op3(seq, data, dst); | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| static int seqvideo_decode_init(AVCodecContext *avctx) | |||
| { | |||
| SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data; | |||
| seq->avctx = avctx; | |||
| avctx->pix_fmt = PIX_FMT_PAL8; | |||
| avctx->has_b_frames = 0; | |||
| seq->frame.data[0] = NULL; | |||
| return 0; | |||
| } | |||
| static int seqvideo_decode_frame(AVCodecContext *avctx, | |||
| void *data, int *data_size, | |||
| uint8_t *buf, int buf_size) | |||
| { | |||
| SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data; | |||
| seq->frame.reference = 1; | |||
| seq->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | |||
| if (avctx->reget_buffer(avctx, &seq->frame)) { | |||
| av_log(seq->avctx, AV_LOG_ERROR, "tiertexseqvideo: reget_buffer() failed\n"); | |||
| return -1; | |||
| } | |||
| seqvideo_decode(seq, buf, buf_size); | |||
| *data_size = sizeof(AVFrame); | |||
| *(AVFrame *)data = seq->frame; | |||
| return buf_size; | |||
| } | |||
| static int seqvideo_decode_end(AVCodecContext *avctx) | |||
| { | |||
| SeqVideoContext *seq = (SeqVideoContext *)avctx->priv_data; | |||
| if (seq->frame.data[0]) | |||
| avctx->release_buffer(avctx, &seq->frame); | |||
| return 0; | |||
| } | |||
| AVCodec tiertexseqvideo_decoder = { | |||
| "tiertexseqvideo", | |||
| CODEC_TYPE_VIDEO, | |||
| CODEC_ID_TIERTEXSEQVIDEO, | |||
| sizeof(SeqVideoContext), | |||
| seqvideo_decode_init, | |||
| NULL, | |||
| seqvideo_decode_end, | |||
| seqvideo_decode_frame, | |||
| CODEC_CAP_DR1, | |||
| }; | |||
| @@ -130,6 +130,7 @@ OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood.o | |||
| OBJS-$(CONFIG_WV_DEMUXER) += wv.o | |||
| OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o | |||
| OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o | |||
| OBJS-$(CONFIG_TIERTEXSEQ_DEMUXER) += tiertexseq.o | |||
| # image formats | |||
| OBJS+= pnm.o yuv.o png.o jpeg.o gifdec.o sgi.o | |||
| @@ -478,6 +478,9 @@ void av_register_all(void) | |||
| #ifdef CONFIG_YUV4MPEGPIPE_DEMUXER | |||
| av_register_input_format(&yuv4mpegpipe_demuxer); | |||
| #endif | |||
| #ifdef CONFIG_TIERTEXSEQ_DEMUXER | |||
| av_register_input_format(&tiertexseq_demuxer); | |||
| #endif | |||
| /* image formats */ | |||
| #if 0 | |||
| @@ -162,6 +162,7 @@ extern AVInputFormat wsvqa_demuxer; | |||
| extern AVInputFormat wv_demuxer; | |||
| extern AVOutputFormat yuv4mpegpipe_muxer; | |||
| extern AVInputFormat yuv4mpegpipe_demuxer; | |||
| extern AVInputFormat tiertexseq_demuxer; | |||
| /* raw.c */ | |||
| int pcm_read_seek(AVFormatContext *s, | |||
| @@ -25,8 +25,8 @@ | |||
| extern "C" { | |||
| #endif | |||
| #define LIBAVFORMAT_VERSION_INT ((50<<16)+(5<<8)+0) | |||
| #define LIBAVFORMAT_VERSION 50.5.0 | |||
| #define LIBAVFORMAT_VERSION_INT ((50<<16)+(6<<8)+0) | |||
| #define LIBAVFORMAT_VERSION 50.6.0 | |||
| #define LIBAVFORMAT_BUILD LIBAVFORMAT_VERSION_INT | |||
| #define LIBAVFORMAT_IDENT "Lavf" AV_STRINGIFY(LIBAVFORMAT_VERSION) | |||
| @@ -0,0 +1,305 @@ | |||
| /* | |||
| * Tiertex Limited SEQ File Demuxer | |||
| * Copyright (c) 2006 Gregory Montoir (cyx@users.sourceforge.net) | |||
| * | |||
| * This file is part of FFmpeg. | |||
| * | |||
| * FFmpeg is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU Lesser General Public | |||
| * License as published by the Free Software Foundation; either | |||
| * version 2.1 of the License, or (at your option) any later version. | |||
| * | |||
| * FFmpeg is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| * Lesser General Public License for more details. | |||
| * | |||
| * You should have received a copy of the GNU Lesser General Public | |||
| * License along with FFmpeg; if not, write to the Free Software | |||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
| */ | |||
| /** | |||
| * @file tiertexseq.c | |||
| * Tiertex Limited SEQ file demuxer | |||
| */ | |||
| #include "avformat.h" | |||
| #define SEQ_FRAME_SIZE 6144 | |||
| #define SEQ_FRAME_W 256 | |||
| #define SEQ_FRAME_H 128 | |||
| #define SEQ_NUM_FRAME_BUFFERS 30 | |||
| #define SEQ_AUDIO_BUFFER_SIZE 882 | |||
| #define SEQ_SAMPLE_RATE 22050 | |||
| #define SEQ_FRAME_RATE 25 | |||
| typedef struct TiertexSeqFrameBuffer { | |||
| int fill_size; | |||
| int data_size; | |||
| unsigned char *data; | |||
| } TiertexSeqFrameBuffer; | |||
| typedef struct SeqDemuxContext { | |||
| int audio_stream_index; | |||
| int video_stream_index; | |||
| int current_frame_pts; | |||
| int current_frame_offs; | |||
| TiertexSeqFrameBuffer frame_buffers[SEQ_NUM_FRAME_BUFFERS]; | |||
| int frame_buffers_count; | |||
| unsigned int current_audio_data_size; | |||
| unsigned int current_audio_data_offs; | |||
| unsigned int current_pal_data_size; | |||
| unsigned int current_pal_data_offs; | |||
| unsigned int current_video_data_size; | |||
| unsigned char *current_video_data_ptr; | |||
| int audio_buffer_full; | |||
| } SeqDemuxContext; | |||
| static int seq_probe(AVProbeData *p) | |||
| { | |||
| int i; | |||
| if (p->buf_size < 256) | |||
| return 0; | |||
| /* there's no real header in a .seq file, the only thing they have in common */ | |||
| /* is the first 256 bytes of the file which are always filled with 0 */ | |||
| for (i = 0; i < 256; i++) | |||
| if (p->buf[0] != 0) | |||
| return 0; | |||
| /* only one fourth of the score since the previous check is too naive */ | |||
| return AVPROBE_SCORE_MAX / 4; | |||
| } | |||
| static int seq_init_frame_buffers(SeqDemuxContext *seq, ByteIOContext *pb) | |||
| { | |||
| int i, sz; | |||
| TiertexSeqFrameBuffer *seq_buffer; | |||
| url_fseek(pb, 256, SEEK_SET); | |||
| for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) { | |||
| sz = get_le16(pb); | |||
| if (sz == 0) | |||
| break; | |||
| else { | |||
| seq_buffer = &seq->frame_buffers[i]; | |||
| seq_buffer->fill_size = 0; | |||
| seq_buffer->data_size = sz; | |||
| seq_buffer->data = av_malloc(sz); | |||
| if (!seq_buffer->data) | |||
| return AVERROR_NOMEM; | |||
| } | |||
| } | |||
| seq->frame_buffers_count = i; | |||
| return 0; | |||
| } | |||
| static int seq_fill_buffer(SeqDemuxContext *seq, ByteIOContext *pb, int buffer_num, unsigned int data_offs, int data_size) | |||
| { | |||
| TiertexSeqFrameBuffer *seq_buffer; | |||
| if (buffer_num >= SEQ_NUM_FRAME_BUFFERS) | |||
| return AVERROR_INVALIDDATA; | |||
| seq_buffer = &seq->frame_buffers[buffer_num]; | |||
| if (seq_buffer->fill_size + data_size > seq_buffer->data_size) | |||
| return AVERROR_INVALIDDATA; | |||
| url_fseek(pb, seq->current_frame_offs + data_offs, SEEK_SET); | |||
| if (get_buffer(pb, seq_buffer->data + seq_buffer->fill_size, data_size) != data_size) | |||
| return AVERROR_IO; | |||
| seq_buffer->fill_size += data_size; | |||
| return 0; | |||
| } | |||
| static int seq_parse_frame_data(SeqDemuxContext *seq, ByteIOContext *pb) | |||
| { | |||
| unsigned int offset_table[4], buffer_num[4]; | |||
| TiertexSeqFrameBuffer *seq_buffer; | |||
| int i, e; | |||
| seq->current_frame_offs += SEQ_FRAME_SIZE; | |||
| url_fseek(pb, seq->current_frame_offs, SEEK_SET); | |||
| /* sound data */ | |||
| seq->current_audio_data_offs = get_le16(pb); | |||
| if (seq->current_audio_data_offs != 0) { | |||
| seq->current_audio_data_size = SEQ_AUDIO_BUFFER_SIZE * 2; | |||
| } else { | |||
| seq->current_audio_data_size = 0; | |||
| } | |||
| /* palette data */ | |||
| seq->current_pal_data_offs = get_le16(pb); | |||
| if (seq->current_pal_data_offs != 0) { | |||
| seq->current_pal_data_size = 768; | |||
| } else { | |||
| seq->current_pal_data_size = 0; | |||
| } | |||
| /* video data */ | |||
| for (i = 0; i < 4; i++) | |||
| buffer_num[i] = get_byte(pb); | |||
| for (i = 0; i < 4; i++) | |||
| offset_table[i] = get_le16(pb); | |||
| for (i = 0; i < 3; i++) { | |||
| if (offset_table[i] != 0) { | |||
| for (e = i + 1; e < 4 && offset_table[e] == 0; e++); | |||
| seq_fill_buffer(seq, pb, buffer_num[1 + i], | |||
| offset_table[i], | |||
| offset_table[e] - offset_table[i]); | |||
| } | |||
| } | |||
| if (buffer_num[0] != 255) { | |||
| seq_buffer = &seq->frame_buffers[buffer_num[0]]; | |||
| seq->current_video_data_size = seq_buffer->fill_size; | |||
| seq->current_video_data_ptr = seq_buffer->data; | |||
| seq_buffer->fill_size = 0; | |||
| } else { | |||
| seq->current_video_data_size = 0; | |||
| seq->current_video_data_ptr = 0; | |||
| } | |||
| return 0; | |||
| } | |||
| static int seq_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||
| { | |||
| int i, rc; | |||
| SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data; | |||
| ByteIOContext *pb = &s->pb; | |||
| AVStream *st; | |||
| /* init internal buffers */ | |||
| rc = seq_init_frame_buffers(seq, pb); | |||
| if (rc) | |||
| return rc; | |||
| seq->current_frame_offs = 0; | |||
| /* preload (no audio data, just buffer operations related data) */ | |||
| for (i = 1; i <= 100; i++) { | |||
| rc = seq_parse_frame_data(seq, pb); | |||
| if (rc) | |||
| return rc; | |||
| } | |||
| seq->current_frame_pts = 0; | |||
| seq->audio_buffer_full = 0; | |||
| /* initialize the video decoder stream */ | |||
| st = av_new_stream(s, 0); | |||
| if (!st) | |||
| return AVERROR_NOMEM; | |||
| av_set_pts_info(st, 32, 1, SEQ_FRAME_RATE); | |||
| seq->video_stream_index = st->index; | |||
| st->codec->codec_type = CODEC_TYPE_VIDEO; | |||
| st->codec->codec_id = CODEC_ID_TIERTEXSEQVIDEO; | |||
| st->codec->codec_tag = 0; /* no fourcc */ | |||
| st->codec->width = SEQ_FRAME_W; | |||
| st->codec->height = SEQ_FRAME_H; | |||
| /* initialize the audio decoder stream */ | |||
| st = av_new_stream(s, 0); | |||
| if (!st) | |||
| return AVERROR_NOMEM; | |||
| av_set_pts_info(st, 32, 1, SEQ_SAMPLE_RATE); | |||
| seq->audio_stream_index = st->index; | |||
| st->codec->codec_type = CODEC_TYPE_AUDIO; | |||
| st->codec->codec_id = CODEC_ID_PCM_S16BE; | |||
| st->codec->codec_tag = 0; /* no tag */ | |||
| st->codec->channels = 1; | |||
| st->codec->sample_rate = SEQ_SAMPLE_RATE; | |||
| st->codec->bits_per_sample = 16; | |||
| st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_sample * st->codec->channels; | |||
| st->codec->block_align = st->codec->channels * st->codec->bits_per_sample; | |||
| return 0; | |||
| } | |||
| static int seq_read_packet(AVFormatContext *s, AVPacket *pkt) | |||
| { | |||
| int rc; | |||
| SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data; | |||
| ByteIOContext *pb = &s->pb; | |||
| if (!seq->audio_buffer_full) { | |||
| rc = seq_parse_frame_data(seq, pb); | |||
| if (rc) | |||
| return rc; | |||
| /* video packet */ | |||
| if (seq->current_pal_data_size + seq->current_video_data_size != 0) { | |||
| if (av_new_packet(pkt, 1 + seq->current_pal_data_size + seq->current_video_data_size)) | |||
| return AVERROR_NOMEM; | |||
| pkt->data[0] = 0; | |||
| if (seq->current_pal_data_size != 0) { | |||
| pkt->data[0] |= 1; | |||
| url_fseek(pb, seq->current_frame_offs + seq->current_pal_data_offs, SEEK_SET); | |||
| if (get_buffer(pb, &pkt->data[1], seq->current_pal_data_size) != seq->current_pal_data_size) | |||
| return AVERROR_IO; | |||
| } | |||
| if (seq->current_video_data_size != 0) { | |||
| pkt->data[0] |= 2; | |||
| memcpy(&pkt->data[1 + seq->current_pal_data_size], | |||
| seq->current_video_data_ptr, | |||
| seq->current_video_data_size); | |||
| } | |||
| pkt->stream_index = seq->video_stream_index; | |||
| pkt->pts = seq->current_frame_pts; | |||
| /* sound buffer will be processed on next read_packet() call */ | |||
| seq->audio_buffer_full = 1; | |||
| return 0; | |||
| } | |||
| } | |||
| /* audio packet */ | |||
| if (seq->current_audio_data_offs == 0) /* end of data reached */ | |||
| return AVERROR_IO; | |||
| url_fseek(pb, seq->current_frame_offs + seq->current_audio_data_offs, SEEK_SET); | |||
| rc = av_get_packet(pb, pkt, seq->current_audio_data_size); | |||
| if (rc < 0) | |||
| return rc; | |||
| pkt->stream_index = seq->audio_stream_index; | |||
| pkt->pts = seq->current_frame_pts++; | |||
| seq->audio_buffer_full = 0; | |||
| return 0; | |||
| } | |||
| static int seq_read_close(AVFormatContext *s) | |||
| { | |||
| int i; | |||
| SeqDemuxContext *seq = (SeqDemuxContext *)s->priv_data; | |||
| for (i = 0; i < SEQ_NUM_FRAME_BUFFERS; i++) | |||
| av_free(seq->frame_buffers[i].data); | |||
| return 0; | |||
| } | |||
| AVInputFormat tiertexseq_demuxer = { | |||
| "tiertexseq", | |||
| "Tiertex Limited SEQ format", | |||
| sizeof(SeqDemuxContext), | |||
| seq_probe, | |||
| seq_read_header, | |||
| seq_read_packet, | |||
| seq_read_close, | |||
| }; | |||