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