• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/ipmovie.c

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