📄 main.cpp
字号:
RMuint8 *p = (RMuint8 *)get_buffer_address (&BPscan, idx); memcpy (p, mp43scan_buffer, mp43scan_status); while (mp43scan_status) { addref_buffer (&(BPscan.B[idx])); buflen = MY_MIN (0xffff, mp43scan_status); ASSERT (buflen); mpegerr = pMpegDecoder->WriteMpegVideo (p, buflen, &(BPscan.B[idx]), 0, 0, 0); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); if (mpegerr == MPEG_DECODER_ERROR_NO_ROOM) { release_buffer (&(BPscan.B[idx])); } mp43scan_status -= buflen; p += buflen; } } else ASSERT (0); mp43scan_status = 0; aviFrameCounter++; return 0; } // end filtering#endif // send 0x000001b6 at the start of every picture // for ms-mpeg4v3 if (flags & AVI_FLAG_CHUNK_START) { pic_startcode[0] = 0x00; pic_startcode[1] = 0x00; pic_startcode[2] = 0x01; pic_startcode[3] = 0xb6; videoTime = aviStartupDelay + ((RMint64)aviFrameCounter * (RMint64)aviTicksPerFrame); DEBUGMSG (0, ("WriteMpegVideo (aviTime0 = %d, videoTime = %d)\n", (RMint32)aviTime0, (RMint32)videoTime)); mpegerr = pMpegDecoder->WriteMpegVideo (pic_startcode, 4, 0, CTS_AVAILABLE_FLAG, aviTime0, videoTime); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); aviFrameCounter++; } flags = 0; } ASSERT (pMpegDecoder); BufferPool *BP; ASSERT (((int)buffer >= (int)avi_buffer) && ((int)buffer < ((int)avi_buffer + (AVI_BUFFERSIZE * AVI_NBUFFERS)))); BP = &BPavi; int idx = ((int)buffer - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); // break this chunk into < 64k blocks RMuint8 *p = buffer; RMuint32 tl = buflen; RMuint32 flag = 0; if (flags & AVI_FLAG_CHUNK_START) { if (buflen > 4) { // if I or P frame if (((buffer[4] & 0xc0) == 0x40) || ((buffer[4] & 0xc0) == 0x00)) { flag = CTS_AVAILABLE_FLAG; videoTime = aviStartupDelay + ((RMint64)aviFrameCounter * (RMint64)aviTicksPerFrame); } } aviFrameCounter++; DEBUGMSG (0, ("(2) aviFrameCounter: %lu\n", aviFrameCounter)); } while (tl) { addref_buffer (&(BP->B[idx])); buflen = MY_MIN (0xffff, tl); DEBUGMSG (0, ("WriteMpegVideo (%d, %d, %d)\n", (RMint32)videoTime, (RMint32)buflen, aviFrameCounter)); DEBUGMSG (0, ("%02x %02x %02x %02x\n", p[0], p[1], p[2], p[3])); ASSERT (buflen); if (KeyFramesOnly) flag = 0; DEBUGMSG (0, ("WriteMpegVideo (KeyFramesOnly = %d, flag = %d, aviTime0 = %d, videoTime = %d)\n", (RMint32)KeyFramesOnly, (RMint32)flag, (RMint32)aviTime0, (RMint32)videoTime)); if (flag) mpegerr = pMpegDecoder->WriteMpegVideo (p, buflen, &(BP->B[idx]), flag, aviTime0, videoTime); else mpegerr = pMpegDecoder->WriteMpegVideo (p, buflen, &(BP->B[idx]), 0, 0, 0); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); if (mpegerr == MPEG_DECODER_ERROR_NO_ROOM) { release_buffer (&(BP->B[idx])); } tl -= buflen; p += buflen; flag = 0; } } else if ((chunkid[2] == 'w') && (chunkid[3] == 'b')) { // audio chunk if ((chunkid[0] == selected_audio_stream[0]) && (chunkid[1] == selected_audio_stream[1])) { DEBUGMSG (0, ("audio chunk (%c%c%c%c, 0x%08lx, %lu, 0x%08lx)\n", chunkid[0], chunkid[1], chunkid[2], chunkid[3], buffer, buflen, flags)); if (selected_audio_stream_format == 0x55) { // mp3 if (pMP3BufferDecoder) { if (pMP3BufferDecoder->DecodeBuffer (buffer, buflen) == MP3_DECODER_ERROR_BAD_MP3_BUFFER) tbytes += (1152 * 2 * NumberOfChannels); } } else if (selected_audio_stream_format == 0x2000) { // ac3 BufferPool *BP; ASSERT (((int)buffer >= (int)avi_buffer) && ((int)buffer < ((int)avi_buffer + (AVI_BUFFERSIZE * AVI_NBUFFERS)))); BP = &BPavi; int idx = ((int)buffer - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); // break this chunk into < 64k blocks RMuint8 *p = buffer; RMuint32 tl = buflen; RMuint32 flag = 0; avi_initial_start = 0; // find the ac3FrameSize if ((buflen > 4) && (ac3FrameSize == 0)) { RMint32 ac3l = buflen; RMuint8 *pac3 = buffer; while (ac3l > 4) { if ((pac3[0] == 0x0b) && (pac3[1] == 0x77)) { int fscod = (pac3[4] >> 6) & 0x3; int frmsizecod = pac3[4] & 0x3f; if ((fscod < 3) && (frmsizecod <= 0x25)) { ac3FrameSize = frmsizecod_table[fscod][frmsizecod] * 2; DEBUGMSG (1, ("ac3FrameSize: %d\n", ac3FrameSize)); break; } } pac3++; ac3l--; } } if (ac3FrameSize) { RMint64 nac3frames = (RMint64)tbytes / ac3FrameSize; if (tbytes % ac3FrameSize) nac3frames++; flag = CTS_AVAILABLE_FLAG; audioTime = aviStartupDelay + ((RMint64)nac3frames * 256 * 6 * (RMint64)aviTimeScale / (RMint64)SamplesPerSecond); } // fill out the firstaccessunitpointer field // to make ac3 sync better int firstaccessunitpointer = 0; if (flag && ac3FrameSize) firstaccessunitpointer = ac3FrameSize - (tbytes % ac3FrameSize); tbytes += buflen; while (tl) { addref_buffer (&(BP->B[idx])); buflen = MY_MIN (0x2000, tl); ASSERT (pMpegDecoder); DEBUGMSG (0, ("WriteAC3 (%d)\n", (RMint32)audioTime)); mpegerr = pMpegDecoder->WriteAC3 (p, buflen, &(BP->B[idx]), flag, aviTime0, audioTime, firstaccessunitpointer); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); tl -= buflen; p += buflen; flag = 0; } } else if (selected_audio_stream_format == 0x2001) { // dts BufferPool *BP; ASSERT (((int)buffer >= (int)avi_buffer) && ((int)buffer < ((int)avi_buffer + (AVI_BUFFERSIZE * AVI_NBUFFERS)))); BP = &BPavi; int idx = ((int)buffer - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); // break this chunk into < 4k blocks RMuint8 *p = buffer; RMuint32 tl = buflen; RMuint32 flag = 0; // find the dts frame size if ((buflen > 4) && ((dtsFrameSize == 0) || (avi_initial_start))) { RMint32 dtsl = buflen; RMuint8 *pdts = buffer; while (dtsl > 4) { if ((pdts[0] == 0x7f) && (pdts[1] == 0xfe) && (pdts[2] == 0x80) && (pdts[3] == 0x01)) { dtsFrameSize = ( ((RMuint32)(pdts[5] & 0x03) << 12) | ((RMuint32)(pdts[6] ) << 4) | ((RMuint32)(pdts[7] & 0xf0) >> 4)); dtsFrameSize++; DEBUGMSG (1, ("dtsFrameSize = %d\n", (RMint32)dtsFrameSize)); p = pdts; buflen = dtsl; tl = buflen; break; } pdts++; dtsl--; } } if (dtsFrameSize == 0) return 0; if ((tbytes == 0) || (avi_initial_start)) { avi_initial_start = 0; RMint64 ndtsframes = (RMint64)tbytes / dtsFrameSize; if (tbytes && (tbytes % dtsFrameSize)) ndtsframes++; flag = CTS_AVAILABLE_FLAG; audioTime = aviStartupDelay + ((RMint64)ndtsframes * 512 * (RMint64)aviTimeScale / (RMint64)SamplesPerSecond); } tbytes += buflen; while (tl) { addref_buffer (&(BP->B[idx])); buflen = MY_MIN (0x1000, tl); ASSERT (pMpegDecoder); DEBUGMSG (0, ("WriteDTS (%d, %d)\n", (RMint32)buflen, (RMint32)audioTime)); DEBUGMSG (flag, ("WriteDTS (%02x %02x %02x %02x, %d)\n", p[0], p[1], p[2], p[3], (RMint32)audioTime)); mpegerr = pMpegDecoder->WriteDTS (p, buflen, &(BP->B[idx]), flag, aviTime0, audioTime, buflen/dtsFrameSize, 0); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); tl -= buflen; p += buflen; flag = 0; } } else if (selected_audio_stream_format == 0x1) { // pcm BufferPool *BP; ASSERT (((int)buffer >= (int)avi_buffer) && ((int)buffer < ((int)avi_buffer + (AVI_BUFFERSIZE * AVI_NBUFFERS)))); BP = &BPavi; int idx = ((int)buffer - (int)BP->start_address) / BP->buffers_size; ASSERT (idx >= 0); // swap bytes RMuint8 *p = buffer; RMuint32 tl = buflen; RMuint32 flag = CTS_AVAILABLE_FLAG; audioTime = aviStartupDelay + ((RMint64)tbytes * (RMint64)aviTimeScale / (RMint64)BytesPerSecond); RMuint8 tmp; for (RMuint32 i=0; i<buflen; i+=2) { tmp = p[0]; p[0] = p[1]; p[1] = tmp; p += 2; } p = buffer; tbytes += buflen; // break this chunk into < 8k blocks while (tl) { addref_buffer (&(BP->B[idx])); buflen = MY_MIN (0x2000, tl); ASSERT (pMpegDecoder); DEBUGMSG (0, ("WritePCM (%d)\n", (RMint32)audioTime)); mpegerr = pMpegDecoder->WritePCM (p, buflen, &(BP->B[idx]), flag, aviTime0, audioTime); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); if (mpegerr == MPEG_DECODER_ERROR_NO_ROOM) { release_buffer (&(BP->B[idx])); } tl -= buflen; p += buflen; flag = 0; } } } else { // ok - multiple audio streams } } else if ((chunkid[2] == 'd') && (chunkid[3] == 'd')) { // divx drm chunk ASSERT (0); } else { // unknown chunk } return 0;}// ***********************************************// end callback functions requied by the avi demux// ***********************************************// perform a seek in an avi fileint avi_seek (int t){ MPEG_DECODER_ERROR mpegerr; RMuint32 vp, ap, ab; if ((selected_audio_stream_format == 0x2001) && (dtsFrameSize == 0)) return -1; // ask the demux to perform a seek if (pAVIDemux->Seek (t, 1, &vp, &ap, &ab) == AVI_DEMUX_ERROR_NO_ERROR) { if (pAVISubtitle) pAVISubtitle->Seek (t); // flush mpeg decoder pMpegDecoder->Stop (); deinit_buffer_pool (&BPavi); deinit_buffer_pool (&BPpcm); deinit_buffer_pool (&BPscan); init_buffer_pool (&BPscan, mp43pending_buffer, 1024*128, N_MP43_SCAN_BUFFER); init_buffer_pool (&BPavi, avi_buffer, AVI_BUFFERSIZE, AVI_NBUFFERS); init_buffer_pool (&BPpcm, pcm_buffer, PCM_BUFFERSIZE, PCM_NBUFFERS); pMpegDecoder->Play (); // calculate the initial audio and video time aviFrameCounter = vp; videoTime = aviStartupDelay + ((RMint64)aviFrameCounter * (RMint64)aviTicksPerFrame); if (ab) { if (selected_audio_stream_format == 0x55) { DEBUGMSG (1, ("calculating the audioTime based on constant bitrate mp3\n")); audioTime = aviStartupDelay + ((RMint64)ap * (RMint64)aviTimeScale / (RMint64)CompressedBytesPerSecond); tbytes = (RMuint32)((RMint64)ap * (RMint64)BytesPerSecond / (RMint64)CompressedBytesPerSecond); } else { DEBUGMSG (1, ("calculating the audioTime based on constant bitrate\n")); avi_initial_start = 1; tbytes = ap; audioTime = aviStartupDelay + ((RMint64)tbytes * (RMint64)aviTimeScale / (RMint64)CompressedBytesPerSecond); } } else { // must be MP3 ASSERT (selected_audio_stream_format == 0x55); DEBUGMSG (1, ("calculating the audioTime based on variable bitrate mp3\n")); audioTime = aviStartupDelay + ((RMint64)ap * (RMint64)1152 * (RMint64)aviTimeScale / (RMint64)SamplesPerSecond); tbytes = (RMint64)ap * (RMint64)1152 * (NumberOfBitsPerSample / 8) * NumberOfChannels; } DEBUGMSG (1, ("aviFrameCounter = %lu\n", aviFrameCounter)); DEBUGMSG (1, ("tbytes = %lu (%d * %d / %d)\n", tbytes, ap, BytesPerSecond, CompressedBytesPerSecond)); aviTime0 = MY_MIN (audioTime, videoTime); if (aviTime0 == 0) aviTime0 = 1; RMint8 text[64]; RMint64 t, hours, minutes, seconds; t = videoTime / aviTimeScale; hours = t / 3600; minutes = (t - hours * 3600) / 60; seconds = t - hours*3600 - minutes*60; DEBUGMSG (1, ("videoTime = %lu (%02d:%02d:%02d)\n", (RMuint32)videoTime, (RMint32)hours, (RMint32)minutes, (RMint32)seconds)); t = audioTime / aviTimeScale; hours = t / 3600; minutes = (t - hours * 3600) / 60; seconds = t - hours*3600 - minutes*60; DEBUGMSG (1, ("audioTime = %lu (%02d:%02d:%02d)\n", (RMuint32)audioTime, (RMint32)hours, (RMint32)minutes, (RMint32)seconds)); DEBUGMSG (1, ("aviTime0 = %lu\n", (RMuint32)aviTime0)); // send an initial VOL header RMuint32 length, i; RMint32 idx = find_free_buffer (&BPavi, 0); ASSERT (idx >= 0); RMuint8 *p = (RMuint8 *)get_buffer_address (&BPavi, idx); length = BPavi.buffers_size; if (msmpeg4v3) { MP43_filter_flush (&MP43Scanner); DEBUGMSG (1, ("create a vol header (seek)\n")); VOLHdrLength = MP43_DSI_Generator (VOLHdr, currentScale, currentRate, currentWidth, currentHeight); addref_buffer (&BPavi.B[idx]); memcpy (p, VOLHdr, VOLHdrLength); mpegerr = pMpegDecoder->WriteMpegVideo (p, VOLHdrLength, &BPavi.B[idx], 0, 0, 0); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); if (mpegerr == MPEG_DECODER_ERROR_NO_ROOM) { release_buffer (&BPavi.B[idx]); } mp43scan_status = 0; } else { // there should always be a vol header at frame 0 pAVIDemux->GetFrame (0, p, &length); p += 8; RMuint8 *pVOLHdr = p; // find the vol header for (i=0; i<length-4; i++) { if ((p[0] == 0x00) && (p[1] == 0x00) && (p[2] == 0x01) && (p[3] == 0xb6)) { ASSERT (pMpegDecoder); ASSERT (i); if (i) { MPEG_DECODER_ERROR mpegerr; DEBUGMSG (1, ("sending volheader: %d bytes\n", i)); addref_buffer (&BPavi.B[idx]); ASSERT (i); mpegerr = pMpegDecoder->WriteMpegVideo (pVOLHdr, i, &BPavi.B[idx], 0, 0, 0); ASSERT (mpegerr == MPEG_DECODER_ERROR_NO_ERROR); if (mpegerr == MPEG_DECODER_ERROR_NO_ROOM) { release_buffer (&BPavi.B[idx]); } } break; } p++; } } } else { DEBUGMSG (1, ("pAVIDemux->Seek (%d) failed.\n", t)); return -1; } return 0;}// send key frames onlyint avi_keyframesonly (int direction){ MPEG_DECODER_ERROR mpegerr; RMuint32 vp; // set the delay between key frames // a longer delay will forward/reverse seem slower // a shorter delay will make forward/reverse seem faster // note that the quickest the frames will advance also // depends on the seeking speed of your dvdrom drive pAVIDemux->SetKeyFrameDelay (250); DEBUGMSG (1, ("avi_keyframesonly ...\n")); AVI_DEMUX_ERROR errorcode; errorcode = pAVIDemux->KeyFramesOnly ((RMint32)direction);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -