Libav
|
00001 /* 00002 * Interplay MVE File Demuxer 00003 * Copyright (c) 2003 The ffmpeg Project 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00035 #include "libavutil/intreadwrite.h" 00036 #include "avformat.h" 00037 00038 /* debugging support: #define DEBUG_IPMOVIE as non-zero to see extremely 00039 * verbose information about the demux process */ 00040 #define DEBUG_IPMOVIE 0 00041 00042 #if DEBUG_IPMOVIE 00043 #undef printf 00044 #define debug_ipmovie printf 00045 #else 00046 static inline void debug_ipmovie(const char *format, ...) { } 00047 #endif 00048 00049 #define CHUNK_PREAMBLE_SIZE 4 00050 #define OPCODE_PREAMBLE_SIZE 4 00051 00052 #define CHUNK_INIT_AUDIO 0x0000 00053 #define CHUNK_AUDIO_ONLY 0x0001 00054 #define CHUNK_INIT_VIDEO 0x0002 00055 #define CHUNK_VIDEO 0x0003 00056 #define CHUNK_SHUTDOWN 0x0004 00057 #define CHUNK_END 0x0005 00058 /* these last types are used internally */ 00059 #define CHUNK_DONE 0xFFFC 00060 #define CHUNK_NOMEM 0xFFFD 00061 #define CHUNK_EOF 0xFFFE 00062 #define CHUNK_BAD 0xFFFF 00063 00064 #define OPCODE_END_OF_STREAM 0x00 00065 #define OPCODE_END_OF_CHUNK 0x01 00066 #define OPCODE_CREATE_TIMER 0x02 00067 #define OPCODE_INIT_AUDIO_BUFFERS 0x03 00068 #define OPCODE_START_STOP_AUDIO 0x04 00069 #define OPCODE_INIT_VIDEO_BUFFERS 0x05 00070 #define OPCODE_UNKNOWN_06 0x06 00071 #define OPCODE_SEND_BUFFER 0x07 00072 #define OPCODE_AUDIO_FRAME 0x08 00073 #define OPCODE_SILENCE_FRAME 0x09 00074 #define OPCODE_INIT_VIDEO_MODE 0x0A 00075 #define OPCODE_CREATE_GRADIENT 0x0B 00076 #define OPCODE_SET_PALETTE 0x0C 00077 #define OPCODE_SET_PALETTE_COMPRESSED 0x0D 00078 #define OPCODE_UNKNOWN_0E 0x0E 00079 #define OPCODE_SET_DECODING_MAP 0x0F 00080 #define OPCODE_UNKNOWN_10 0x10 00081 #define OPCODE_VIDEO_DATA 0x11 00082 #define OPCODE_UNKNOWN_12 0x12 00083 #define OPCODE_UNKNOWN_13 0x13 00084 #define OPCODE_UNKNOWN_14 0x14 00085 #define OPCODE_UNKNOWN_15 0x15 00086 00087 #define PALETTE_COUNT 256 00088 00089 typedef struct IPMVEContext { 00090 00091 unsigned char *buf; 00092 int buf_size; 00093 00094 uint64_t frame_pts_inc; 00095 00096 unsigned int video_bpp; 00097 unsigned int video_width; 00098 unsigned int video_height; 00099 int64_t video_pts; 00100 00101 unsigned int audio_bits; 00102 unsigned int audio_channels; 00103 unsigned int audio_sample_rate; 00104 enum CodecID audio_type; 00105 unsigned int audio_frame_count; 00106 00107 int video_stream_index; 00108 int audio_stream_index; 00109 00110 int64_t audio_chunk_offset; 00111 int audio_chunk_size; 00112 int64_t video_chunk_offset; 00113 int video_chunk_size; 00114 int64_t decode_map_chunk_offset; 00115 int decode_map_chunk_size; 00116 00117 int64_t next_chunk_offset; 00118 00119 AVPaletteControl palette_control; 00120 00121 } IPMVEContext; 00122 00123 static int load_ipmovie_packet(IPMVEContext *s, ByteIOContext *pb, 00124 AVPacket *pkt) { 00125 00126 int chunk_type; 00127 00128 if (s->audio_chunk_offset) { 00129 00130 /* adjust for PCM audio by skipping chunk header */ 00131 if (s->audio_type != CODEC_ID_INTERPLAY_DPCM) { 00132 s->audio_chunk_offset += 6; 00133 s->audio_chunk_size -= 6; 00134 } 00135 00136 url_fseek(pb, s->audio_chunk_offset, SEEK_SET); 00137 s->audio_chunk_offset = 0; 00138 00139 if (s->audio_chunk_size != av_get_packet(pb, pkt, s->audio_chunk_size)) 00140 return CHUNK_EOF; 00141 00142 pkt->stream_index = s->audio_stream_index; 00143 pkt->pts = s->audio_frame_count; 00144 00145 /* audio frame maintenance */ 00146 if (s->audio_type != CODEC_ID_INTERPLAY_DPCM) 00147 s->audio_frame_count += 00148 (s->audio_chunk_size / s->audio_channels / (s->audio_bits / 8)); 00149 else 00150 s->audio_frame_count += 00151 (s->audio_chunk_size - 6) / s->audio_channels; 00152 00153 debug_ipmovie("sending audio frame with pts %"PRId64" (%d audio frames)\n", 00154 pkt->pts, s->audio_frame_count); 00155 00156 chunk_type = CHUNK_VIDEO; 00157 00158 } else if (s->decode_map_chunk_offset) { 00159 00160 /* send both the decode map and the video data together */ 00161 00162 if (av_new_packet(pkt, s->decode_map_chunk_size + s->video_chunk_size)) 00163 return CHUNK_NOMEM; 00164 00165 pkt->pos= s->decode_map_chunk_offset; 00166 url_fseek(pb, s->decode_map_chunk_offset, SEEK_SET); 00167 s->decode_map_chunk_offset = 0; 00168 00169 if (get_buffer(pb, pkt->data, s->decode_map_chunk_size) != 00170 s->decode_map_chunk_size) { 00171 av_free_packet(pkt); 00172 return CHUNK_EOF; 00173 } 00174 00175 url_fseek(pb, s->video_chunk_offset, SEEK_SET); 00176 s->video_chunk_offset = 0; 00177 00178 if (get_buffer(pb, pkt->data + s->decode_map_chunk_size, 00179 s->video_chunk_size) != s->video_chunk_size) { 00180 av_free_packet(pkt); 00181 return CHUNK_EOF; 00182 } 00183 00184 pkt->stream_index = s->video_stream_index; 00185 pkt->pts = s->video_pts; 00186 00187 debug_ipmovie("sending video frame with pts %"PRId64"\n", 00188 pkt->pts); 00189 00190 s->video_pts += s->frame_pts_inc; 00191 00192 chunk_type = CHUNK_VIDEO; 00193 00194 } else { 00195 00196 url_fseek(pb, s->next_chunk_offset, SEEK_SET); 00197 chunk_type = CHUNK_DONE; 00198 00199 } 00200 00201 return chunk_type; 00202 } 00203 00204 /* This function loads and processes a single chunk in an IP movie file. 00205 * It returns the type of chunk that was processed. */ 00206 static int process_ipmovie_chunk(IPMVEContext *s, ByteIOContext *pb, 00207 AVPacket *pkt) 00208 { 00209 unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE]; 00210 int chunk_type; 00211 int chunk_size; 00212 unsigned char opcode_preamble[OPCODE_PREAMBLE_SIZE]; 00213 unsigned char opcode_type; 00214 unsigned char opcode_version; 00215 int opcode_size; 00216 unsigned char scratch[1024]; 00217 int i, j; 00218 int first_color, last_color; 00219 int audio_flags; 00220 unsigned char r, g, b; 00221 00222 /* see if there are any pending packets */ 00223 chunk_type = load_ipmovie_packet(s, pb, pkt); 00224 if (chunk_type != CHUNK_DONE) 00225 return chunk_type; 00226 00227 /* read the next chunk, wherever the file happens to be pointing */ 00228 if (url_feof(pb)) 00229 return CHUNK_EOF; 00230 if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) != 00231 CHUNK_PREAMBLE_SIZE) 00232 return CHUNK_BAD; 00233 chunk_size = AV_RL16(&chunk_preamble[0]); 00234 chunk_type = AV_RL16(&chunk_preamble[2]); 00235 00236 debug_ipmovie("chunk type 0x%04X, 0x%04X bytes: ", chunk_type, chunk_size); 00237 00238 switch (chunk_type) { 00239 00240 case CHUNK_INIT_AUDIO: 00241 debug_ipmovie("initialize audio\n"); 00242 break; 00243 00244 case CHUNK_AUDIO_ONLY: 00245 debug_ipmovie("audio only\n"); 00246 break; 00247 00248 case CHUNK_INIT_VIDEO: 00249 debug_ipmovie("initialize video\n"); 00250 break; 00251 00252 case CHUNK_VIDEO: 00253 debug_ipmovie("video (and audio)\n"); 00254 break; 00255 00256 case CHUNK_SHUTDOWN: 00257 debug_ipmovie("shutdown\n"); 00258 break; 00259 00260 case CHUNK_END: 00261 debug_ipmovie("end\n"); 00262 break; 00263 00264 default: 00265 debug_ipmovie("invalid chunk\n"); 00266 chunk_type = CHUNK_BAD; 00267 break; 00268 00269 } 00270 00271 while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) { 00272 00273 /* read the next chunk, wherever the file happens to be pointing */ 00274 if (url_feof(pb)) { 00275 chunk_type = CHUNK_EOF; 00276 break; 00277 } 00278 if (get_buffer(pb, opcode_preamble, CHUNK_PREAMBLE_SIZE) != 00279 CHUNK_PREAMBLE_SIZE) { 00280 chunk_type = CHUNK_BAD; 00281 break; 00282 } 00283 00284 opcode_size = AV_RL16(&opcode_preamble[0]); 00285 opcode_type = opcode_preamble[2]; 00286 opcode_version = opcode_preamble[3]; 00287 00288 chunk_size -= OPCODE_PREAMBLE_SIZE; 00289 chunk_size -= opcode_size; 00290 if (chunk_size < 0) { 00291 debug_ipmovie("chunk_size countdown just went negative\n"); 00292 chunk_type = CHUNK_BAD; 00293 break; 00294 } 00295 00296 debug_ipmovie(" opcode type %02X, version %d, 0x%04X bytes: ", 00297 opcode_type, opcode_version, opcode_size); 00298 switch (opcode_type) { 00299 00300 case OPCODE_END_OF_STREAM: 00301 debug_ipmovie("end of stream\n"); 00302 url_fseek(pb, opcode_size, SEEK_CUR); 00303 break; 00304 00305 case OPCODE_END_OF_CHUNK: 00306 debug_ipmovie("end of chunk\n"); 00307 url_fseek(pb, opcode_size, SEEK_CUR); 00308 break; 00309 00310 case OPCODE_CREATE_TIMER: 00311 debug_ipmovie("create timer\n"); 00312 if ((opcode_version > 0) || (opcode_size > 6)) { 00313 debug_ipmovie("bad create_timer opcode\n"); 00314 chunk_type = CHUNK_BAD; 00315 break; 00316 } 00317 if (get_buffer(pb, scratch, opcode_size) != 00318 opcode_size) { 00319 chunk_type = CHUNK_BAD; 00320 break; 00321 } 00322 s->frame_pts_inc = ((uint64_t)AV_RL32(&scratch[0])) * AV_RL16(&scratch[4]); 00323 debug_ipmovie(" %.2f frames/second (timer div = %d, subdiv = %d)\n", 00324 1000000.0/s->frame_pts_inc, AV_RL32(&scratch[0]), AV_RL16(&scratch[4])); 00325 break; 00326 00327 case OPCODE_INIT_AUDIO_BUFFERS: 00328 debug_ipmovie("initialize audio buffers\n"); 00329 if ((opcode_version > 1) || (opcode_size > 10)) { 00330 debug_ipmovie("bad init_audio_buffers opcode\n"); 00331 chunk_type = CHUNK_BAD; 00332 break; 00333 } 00334 if (get_buffer(pb, scratch, opcode_size) != 00335 opcode_size) { 00336 chunk_type = CHUNK_BAD; 00337 break; 00338 } 00339 s->audio_sample_rate = AV_RL16(&scratch[4]); 00340 audio_flags = AV_RL16(&scratch[2]); 00341 /* bit 0 of the flags: 0 = mono, 1 = stereo */ 00342 s->audio_channels = (audio_flags & 1) + 1; 00343 /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */ 00344 s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8; 00345 /* bit 2 indicates compressed audio in version 1 opcode */ 00346 if ((opcode_version == 1) && (audio_flags & 0x4)) 00347 s->audio_type = CODEC_ID_INTERPLAY_DPCM; 00348 else if (s->audio_bits == 16) 00349 s->audio_type = CODEC_ID_PCM_S16LE; 00350 else 00351 s->audio_type = CODEC_ID_PCM_U8; 00352 debug_ipmovie("audio: %d bits, %d Hz, %s, %s format\n", 00353 s->audio_bits, 00354 s->audio_sample_rate, 00355 (s->audio_channels == 2) ? "stereo" : "mono", 00356 (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ? 00357 "Interplay audio" : "PCM"); 00358 break; 00359 00360 case OPCODE_START_STOP_AUDIO: 00361 debug_ipmovie("start/stop audio\n"); 00362 url_fseek(pb, opcode_size, SEEK_CUR); 00363 break; 00364 00365 case OPCODE_INIT_VIDEO_BUFFERS: 00366 debug_ipmovie("initialize video buffers\n"); 00367 if ((opcode_version > 2) || (opcode_size > 8)) { 00368 debug_ipmovie("bad init_video_buffers opcode\n"); 00369 chunk_type = CHUNK_BAD; 00370 break; 00371 } 00372 if (get_buffer(pb, scratch, opcode_size) != 00373 opcode_size) { 00374 chunk_type = CHUNK_BAD; 00375 break; 00376 } 00377 s->video_width = AV_RL16(&scratch[0]) * 8; 00378 s->video_height = AV_RL16(&scratch[2]) * 8; 00379 if (opcode_version < 2 || !AV_RL16(&scratch[6])) { 00380 s->video_bpp = 8; 00381 } else { 00382 s->video_bpp = 16; 00383 } 00384 debug_ipmovie("video resolution: %d x %d\n", 00385 s->video_width, s->video_height); 00386 break; 00387 00388 case OPCODE_UNKNOWN_06: 00389 case OPCODE_UNKNOWN_0E: 00390 case OPCODE_UNKNOWN_10: 00391 case OPCODE_UNKNOWN_12: 00392 case OPCODE_UNKNOWN_13: 00393 case OPCODE_UNKNOWN_14: 00394 case OPCODE_UNKNOWN_15: 00395 debug_ipmovie("unknown (but documented) opcode %02X\n", opcode_type); 00396 url_fseek(pb, opcode_size, SEEK_CUR); 00397 break; 00398 00399 case OPCODE_SEND_BUFFER: 00400 debug_ipmovie("send buffer\n"); 00401 url_fseek(pb, opcode_size, SEEK_CUR); 00402 break; 00403 00404 case OPCODE_AUDIO_FRAME: 00405 debug_ipmovie("audio frame\n"); 00406 00407 /* log position and move on for now */ 00408 s->audio_chunk_offset = url_ftell(pb); 00409 s->audio_chunk_size = opcode_size; 00410 url_fseek(pb, opcode_size, SEEK_CUR); 00411 break; 00412 00413 case OPCODE_SILENCE_FRAME: 00414 debug_ipmovie("silence frame\n"); 00415 url_fseek(pb, opcode_size, SEEK_CUR); 00416 break; 00417 00418 case OPCODE_INIT_VIDEO_MODE: 00419 debug_ipmovie("initialize video mode\n"); 00420 url_fseek(pb, opcode_size, SEEK_CUR); 00421 break; 00422 00423 case OPCODE_CREATE_GRADIENT: 00424 debug_ipmovie("create gradient\n"); 00425 url_fseek(pb, opcode_size, SEEK_CUR); 00426 break; 00427 00428 case OPCODE_SET_PALETTE: 00429 debug_ipmovie("set palette\n"); 00430 /* check for the logical maximum palette size 00431 * (3 * 256 + 4 bytes) */ 00432 if (opcode_size > 0x304) { 00433 debug_ipmovie("demux_ipmovie: set_palette opcode too large\n"); 00434 chunk_type = CHUNK_BAD; 00435 break; 00436 } 00437 if (get_buffer(pb, scratch, opcode_size) != opcode_size) { 00438 chunk_type = CHUNK_BAD; 00439 break; 00440 } 00441 00442 /* load the palette into internal data structure */ 00443 first_color = AV_RL16(&scratch[0]); 00444 last_color = first_color + AV_RL16(&scratch[2]) - 1; 00445 /* sanity check (since they are 16 bit values) */ 00446 if ((first_color > 0xFF) || (last_color > 0xFF)) { 00447 debug_ipmovie("demux_ipmovie: set_palette indexes out of range (%d -> %d)\n", 00448 first_color, last_color); 00449 chunk_type = CHUNK_BAD; 00450 break; 00451 } 00452 j = 4; /* offset of first palette data */ 00453 for (i = first_color; i <= last_color; i++) { 00454 /* the palette is stored as a 6-bit VGA palette, thus each 00455 * component is shifted up to a 8-bit range */ 00456 r = scratch[j++] * 4; 00457 g = scratch[j++] * 4; 00458 b = scratch[j++] * 4; 00459 s->palette_control.palette[i] = (r << 16) | (g << 8) | (b); 00460 } 00461 /* indicate a palette change */ 00462 s->palette_control.palette_changed = 1; 00463 break; 00464 00465 case OPCODE_SET_PALETTE_COMPRESSED: 00466 debug_ipmovie("set palette compressed\n"); 00467 url_fseek(pb, opcode_size, SEEK_CUR); 00468 break; 00469 00470 case OPCODE_SET_DECODING_MAP: 00471 debug_ipmovie("set decoding map\n"); 00472 00473 /* log position and move on for now */ 00474 s->decode_map_chunk_offset = url_ftell(pb); 00475 s->decode_map_chunk_size = opcode_size; 00476 url_fseek(pb, opcode_size, SEEK_CUR); 00477 break; 00478 00479 case OPCODE_VIDEO_DATA: 00480 debug_ipmovie("set video data\n"); 00481 00482 /* log position and move on for now */ 00483 s->video_chunk_offset = url_ftell(pb); 00484 s->video_chunk_size = opcode_size; 00485 url_fseek(pb, opcode_size, SEEK_CUR); 00486 break; 00487 00488 default: 00489 debug_ipmovie("*** unknown opcode type\n"); 00490 chunk_type = CHUNK_BAD; 00491 break; 00492 00493 } 00494 } 00495 00496 /* make a note of where the stream is sitting */ 00497 s->next_chunk_offset = url_ftell(pb); 00498 00499 /* dispatch the first of any pending packets */ 00500 if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY)) 00501 chunk_type = load_ipmovie_packet(s, pb, pkt); 00502 00503 return chunk_type; 00504 } 00505 00506 static const char signature[] = "Interplay MVE File\x1A\0\x1A"; 00507 00508 static int ipmovie_probe(AVProbeData *p) 00509 { 00510 uint8_t *b = p->buf; 00511 uint8_t *b_end = p->buf + p->buf_size - sizeof(signature); 00512 do { 00513 if (memcmp(b++, signature, sizeof(signature)) == 0) 00514 return AVPROBE_SCORE_MAX; 00515 } while (b < b_end); 00516 00517 return 0; 00518 } 00519 00520 static int ipmovie_read_header(AVFormatContext *s, 00521 AVFormatParameters *ap) 00522 { 00523 IPMVEContext *ipmovie = s->priv_data; 00524 ByteIOContext *pb = s->pb; 00525 AVPacket pkt; 00526 AVStream *st; 00527 unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE]; 00528 int chunk_type; 00529 uint8_t signature_buffer[sizeof(signature)]; 00530 00531 get_buffer(pb, signature_buffer, sizeof(signature_buffer)); 00532 while (memcmp(signature_buffer, signature, sizeof(signature))) { 00533 memmove(signature_buffer, signature_buffer + 1, sizeof(signature_buffer) - 1); 00534 signature_buffer[sizeof(signature_buffer) - 1] = get_byte(pb); 00535 if (url_feof(pb)) 00536 return AVERROR_EOF; 00537 } 00538 /* initialize private context members */ 00539 ipmovie->video_pts = ipmovie->audio_frame_count = 0; 00540 ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset = 00541 ipmovie->decode_map_chunk_offset = 0; 00542 00543 /* on the first read, this will position the stream at the first chunk */ 00544 ipmovie->next_chunk_offset = url_ftell(pb) + 4; 00545 00546 /* process the first chunk which should be CHUNK_INIT_VIDEO */ 00547 if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) 00548 return AVERROR_INVALIDDATA; 00549 00550 /* peek ahead to the next chunk-- if it is an init audio chunk, process 00551 * it; if it is the first video chunk, this is a silent file */ 00552 if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) != 00553 CHUNK_PREAMBLE_SIZE) 00554 return AVERROR(EIO); 00555 chunk_type = AV_RL16(&chunk_preamble[2]); 00556 url_fseek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR); 00557 00558 if (chunk_type == CHUNK_VIDEO) 00559 ipmovie->audio_type = CODEC_ID_NONE; /* no audio */ 00560 else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO) 00561 return AVERROR_INVALIDDATA; 00562 00563 /* initialize the stream decoders */ 00564 st = av_new_stream(s, 0); 00565 if (!st) 00566 return AVERROR(ENOMEM); 00567 av_set_pts_info(st, 63, 1, 1000000); 00568 ipmovie->video_stream_index = st->index; 00569 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00570 st->codec->codec_id = CODEC_ID_INTERPLAY_VIDEO; 00571 st->codec->codec_tag = 0; /* no fourcc */ 00572 st->codec->width = ipmovie->video_width; 00573 st->codec->height = ipmovie->video_height; 00574 st->codec->bits_per_coded_sample = ipmovie->video_bpp; 00575 00576 /* palette considerations */ 00577 st->codec->palctrl = &ipmovie->palette_control; 00578 00579 if (ipmovie->audio_type) { 00580 st = av_new_stream(s, 0); 00581 if (!st) 00582 return AVERROR(ENOMEM); 00583 av_set_pts_info(st, 32, 1, ipmovie->audio_sample_rate); 00584 ipmovie->audio_stream_index = st->index; 00585 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00586 st->codec->codec_id = ipmovie->audio_type; 00587 st->codec->codec_tag = 0; /* no tag */ 00588 st->codec->channels = ipmovie->audio_channels; 00589 st->codec->sample_rate = ipmovie->audio_sample_rate; 00590 st->codec->bits_per_coded_sample = ipmovie->audio_bits; 00591 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 00592 st->codec->bits_per_coded_sample; 00593 if (st->codec->codec_id == CODEC_ID_INTERPLAY_DPCM) 00594 st->codec->bit_rate /= 2; 00595 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; 00596 } 00597 00598 return 0; 00599 } 00600 00601 static int ipmovie_read_packet(AVFormatContext *s, 00602 AVPacket *pkt) 00603 { 00604 IPMVEContext *ipmovie = s->priv_data; 00605 ByteIOContext *pb = s->pb; 00606 int ret; 00607 00608 ret = process_ipmovie_chunk(ipmovie, pb, pkt); 00609 if (ret == CHUNK_BAD) 00610 ret = AVERROR_INVALIDDATA; 00611 else if (ret == CHUNK_EOF) 00612 ret = AVERROR(EIO); 00613 else if (ret == CHUNK_NOMEM) 00614 ret = AVERROR(ENOMEM); 00615 else if (ret == CHUNK_VIDEO) 00616 ret = 0; 00617 else 00618 ret = -1; 00619 00620 return ret; 00621 } 00622 00623 AVInputFormat ipmovie_demuxer = { 00624 "ipmovie", 00625 NULL_IF_CONFIG_SMALL("Interplay MVE format"), 00626 sizeof(IPMVEContext), 00627 ipmovie_probe, 00628 ipmovie_read_header, 00629 ipmovie_read_packet, 00630 };