📄 ipmovie.c
字号:
debug_ipmovie("create timer\n"); if ((opcode_version > 0) || (opcode_size > 6)) { debug_ipmovie("bad create_timer opcode\n"); chunk_type = CHUNK_BAD; break; } if (get_buffer(pb, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; } s->fps = 1000000.0 / (LE_32(&scratch[0]) * LE_16(&scratch[4])); s->frame_pts_inc = 90000 / s->fps; debug_ipmovie(" %.2f frames/second (timer div = %d, subdiv = %d)\n", s->fps, LE_32(&scratch[0]), LE_16(&scratch[4])); break; case OPCODE_INIT_AUDIO_BUFFERS: debug_ipmovie("initialize audio buffers\n"); if ((opcode_version > 1) || (opcode_size > 10)) { debug_ipmovie("bad init_audio_buffers opcode\n"); chunk_type = CHUNK_BAD; break; } if (get_buffer(pb, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; } s->audio_sample_rate = LE_16(&scratch[4]); audio_flags = LE_16(&scratch[2]); /* bit 0 of the flags: 0 = mono, 1 = stereo */ s->audio_channels = (audio_flags & 1) + 1; /* bit 1 of the flags: 0 = 8 bit, 1 = 16 bit */ s->audio_bits = (((audio_flags >> 1) & 1) + 1) * 8; /* bit 2 indicates compressed audio in version 1 opcode */ if ((opcode_version == 1) && (audio_flags & 0x4)) s->audio_type = CODEC_ID_INTERPLAY_DPCM; else if (s->audio_bits == 16) s->audio_type = CODEC_ID_PCM_S16LE; else s->audio_type = CODEC_ID_PCM_U8; debug_ipmovie("audio: %d bits, %d Hz, %s, %s format\n", s->audio_bits, s->audio_sample_rate, (s->audio_channels == 2) ? "stereo" : "mono", (s->audio_type == CODEC_ID_INTERPLAY_DPCM) ? "Interplay audio" : "PCM"); break; case OPCODE_START_STOP_AUDIO: debug_ipmovie("start/stop audio\n"); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_INIT_VIDEO_BUFFERS: debug_ipmovie("initialize video buffers\n"); if ((opcode_version > 2) || (opcode_size > 8)) { debug_ipmovie("bad init_video_buffers opcode\n"); chunk_type = CHUNK_BAD; break; } if (get_buffer(pb, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; } s->video_width = LE_16(&scratch[0]) * 8; s->video_height = LE_16(&scratch[2]) * 8; debug_ipmovie("video resolution: %d x %d\n", s->video_width, s->video_height); break; case OPCODE_UNKNOWN_06: case OPCODE_UNKNOWN_0E: case OPCODE_UNKNOWN_10: case OPCODE_UNKNOWN_12: case OPCODE_UNKNOWN_13: case OPCODE_UNKNOWN_14: case OPCODE_UNKNOWN_15: debug_ipmovie("unknown (but documented) opcode %02X\n", opcode_type); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_SEND_BUFFER: debug_ipmovie("send buffer\n"); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_AUDIO_FRAME: debug_ipmovie("audio frame\n"); /* log position and move on for now */ s->audio_chunk_offset = url_ftell(pb); s->audio_chunk_size = opcode_size; url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_SILENCE_FRAME: debug_ipmovie("silence frame\n"); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_INIT_VIDEO_MODE: debug_ipmovie("initialize video mode\n"); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_CREATE_GRADIENT: debug_ipmovie("create gradient\n"); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_SET_PALETTE: debug_ipmovie("set palette\n"); /* check for the logical maximum palette size * (3 * 256 + 4 bytes) */ if (opcode_size > 0x304) { debug_ipmovie("demux_ipmovie: set_palette opcode too large\n"); chunk_type = CHUNK_BAD; break; } if (get_buffer(pb, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; } /* load the palette into internal data structure */ first_color = LE_16(&scratch[0]); last_color = first_color + LE_16(&scratch[2]) - 1; /* sanity check (since they are 16 bit values) */ if ((first_color > 0xFF) || (last_color > 0xFF)) { debug_ipmovie("demux_ipmovie: set_palette indices out of range (%d -> %d)\n", first_color, last_color); chunk_type = CHUNK_BAD; break; } j = 4; /* offset of first palette data */ for (i = first_color; i <= last_color; i++) { /* the palette is stored as a 6-bit VGA palette, thus each * component is shifted up to a 8-bit range */ r = scratch[j++] * 4; g = scratch[j++] * 4; b = scratch[j++] * 4; s->palette_control.palette[i] = (r << 16) | (g << 8) | (b); } /* indicate a palette change */ s->palette_control.palette_changed = 1; break; case OPCODE_SET_PALETTE_COMPRESSED: debug_ipmovie("set palette compressed\n"); url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_SET_DECODING_MAP: debug_ipmovie("set decoding map\n"); /* log position and move on for now */ s->decode_map_chunk_offset = url_ftell(pb); s->decode_map_chunk_size = opcode_size; url_fseek(pb, opcode_size, SEEK_CUR); break; case OPCODE_VIDEO_DATA: debug_ipmovie("set video data\n"); /* log position and move on for now */ s->video_chunk_offset = url_ftell(pb); s->video_chunk_size = opcode_size; url_fseek(pb, opcode_size, SEEK_CUR); break; default: debug_ipmovie("*** unknown opcode type\n"); chunk_type = CHUNK_BAD; break; } } /* make a note of where the stream is sitting */ s->next_chunk_offset = url_ftell(pb); /* dispatch the first of any pending packets */ if ((chunk_type == CHUNK_VIDEO) || (chunk_type == CHUNK_AUDIO_ONLY)) chunk_type = load_ipmovie_packet(s, pb, pkt); return chunk_type;}static int ipmovie_probe(AVProbeData *p){ if (p->buf_size < IPMOVIE_SIGNATURE_SIZE) return 0; if (strncmp(p->buf, IPMOVIE_SIGNATURE, IPMOVIE_SIGNATURE_SIZE) != 0) return 0; return AVPROBE_SCORE_MAX;}static int ipmovie_read_header(AVFormatContext *s, AVFormatParameters *ap){ IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data; ByteIOContext *pb = &s->pb; AVPacket pkt; AVStream *st; unsigned char chunk_preamble[CHUNK_PREAMBLE_SIZE]; int chunk_type; /* initialize private context members */ ipmovie->video_pts = ipmovie->audio_frame_count = 0; ipmovie->audio_chunk_offset = ipmovie->video_chunk_offset = ipmovie->decode_map_chunk_offset = 0; /* on the first read, this will position the stream at the first chunk */ ipmovie->next_chunk_offset = IPMOVIE_SIGNATURE_SIZE + 6; /* process the first chunk which should be CHUNK_INIT_VIDEO */ if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_VIDEO) return AVERROR_INVALIDDATA; /* peek ahead to the next chunk-- if it is an init audio chunk, process * it; if it is the first video chunk, this is a silent file */ if (get_buffer(pb, chunk_preamble, CHUNK_PREAMBLE_SIZE) != CHUNK_PREAMBLE_SIZE) return AVERROR_IO; chunk_type = LE_16(&chunk_preamble[2]); url_fseek(pb, -CHUNK_PREAMBLE_SIZE, SEEK_CUR); if (chunk_type == CHUNK_VIDEO) ipmovie->audio_type = 0; /* no audio */ else if (process_ipmovie_chunk(ipmovie, pb, &pkt) != CHUNK_INIT_AUDIO) return AVERROR_INVALIDDATA; /* initialize the stream decoders */ st = av_new_stream(s, 0); if (!st) return AVERROR_NOMEM; av_set_pts_info(st, 33, 1, 90000); ipmovie->video_stream_index = st->index; st->codec.codec_type = CODEC_TYPE_VIDEO; st->codec.codec_id = CODEC_ID_INTERPLAY_VIDEO; st->codec.codec_tag = 0; /* no fourcc */ st->codec.width = ipmovie->video_width; st->codec.height = ipmovie->video_height; /* palette considerations */ st->codec.palctrl = &ipmovie->palette_control; if (ipmovie->audio_type) { st = av_new_stream(s, 0); if (!st) return AVERROR_NOMEM; av_set_pts_info(st, 33, 1, 90000); ipmovie->audio_stream_index = st->index; st->codec.codec_type = CODEC_TYPE_AUDIO; st->codec.codec_id = ipmovie->audio_type; st->codec.codec_tag = 0; /* no tag */ st->codec.channels = ipmovie->audio_channels; st->codec.sample_rate = ipmovie->audio_sample_rate; st->codec.bits_per_sample = ipmovie->audio_bits; st->codec.bit_rate = st->codec.channels * st->codec.sample_rate * st->codec.bits_per_sample; if (st->codec.codec_id == CODEC_ID_INTERPLAY_DPCM) st->codec.bit_rate /= 2; st->codec.block_align = st->codec.channels * st->codec.bits_per_sample; } return 0;}static int ipmovie_read_packet(AVFormatContext *s, AVPacket *pkt){ IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data; ByteIOContext *pb = &s->pb; int ret; ret = process_ipmovie_chunk(ipmovie, pb, pkt); if (ret == CHUNK_BAD) ret = AVERROR_INVALIDDATA; else if (ret == CHUNK_EOF) ret = AVERROR_IO; else if (ret == CHUNK_NOMEM) ret = AVERROR_NOMEM; else ret = 0; return ret;}static int ipmovie_read_close(AVFormatContext *s){// IPMVEContext *ipmovie = (IPMVEContext *)s->priv_data; return 0;}static AVInputFormat ipmovie_iformat = { "ipmovie", "Interplay MVE format", sizeof(IPMVEContext), ipmovie_probe, ipmovie_read_header, ipmovie_read_packet, ipmovie_read_close,};int ipmovie_init(void){ av_register_input_format(&ipmovie_iformat); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -