📄 avi.cpp
字号:
DEBUGMSG (1, (" samplespersec: %u\n", m_StreamFormats[m_nStreamFormat].wfx.nSamplesPerSec)); DEBUGMSG (1, (" bitspersample: %u\n", m_StreamFormats[m_nStreamFormat].wfx.wBitsPerSample)); subListLength -= subChunkLength; m_CallbackTable.fseek (m_handle, position+subChunkLength, m_CallbackTable.context); } else { ASSERT (0); DEBUGMSG (1, ("ignoring unknown fcc type = %c%c%c%c\n", AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], fccType) >> 0, AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], fccType) >> 8, AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], fccType) >> 16, AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[m_nStreamFormat], fccType) >> 24)); n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subChunkLength), m_CallbackTable.context); subListLength -= subChunkLength; m_CallbackTable.fseek (m_handle, m_CallbackTable.ftell (m_handle, m_CallbackTable.context)+subChunkLength, m_CallbackTable.context); } m_nStreamFormat++; break; default: DEBUGMSG (1, ("ignoring unknown list type = %c%c%c%c\n", name >> 0, name >> 8, name >> 16, name >> 24)); n = m_CallbackTable.fread (m_handle, &subChunkLength, sizeof(subChunkLength), m_CallbackTable.context); ASSERT (n == sizeof(subChunkLength)); subListLength -= 4; m_CallbackTable.fseek (m_handle, m_CallbackTable.ftell (m_handle, m_CallbackTable.context)+subChunkLength, m_CallbackTable.context); subListLength -= subChunkLength; break; } if (m_nStreamFormat >= AVI_MAX_STREAMS_SUPPORTED) subListLength = 0; } ASSERT ((RMint32)subListLength >= 0); ASSERT ((RMint32)subListLength <= 3); if (((RMint32)subListLength > 0) && ((RMint32)subListLength < 4)) { RMuint32 dummy; m_CallbackTable.fread (m_handle, &dummy, subListLength, m_CallbackTable.context); } } } } break; case AVI_FOURCC ('m','o','v','i'): DEBUGMSG (1, ("movi chunk\n")); m_moviOffset = m_CallbackTable.ftell (m_handle, m_CallbackTable.context); break; default: DEBUGMSG (1, ("unknown list type = %c%c%c%c\n", name >> 0, name >> 8, name >> 16, name >> 24)); break; } m_CallbackTable.fseek (m_handle, listOffset + chunk.Length, m_CallbackTable.context); rifflength -= chunk.Length; break; case AVI_FOURCC ('i','d','x','1'): DEBUGMSG (1, ("idx1 chunk\n")); n = m_CallbackTable.ftell (m_handle, m_CallbackTable.context); m_idx1Offset = n; m_idx1Length = chunk.Length; { // process idx1 chunk AVI_INDEXENTRY tmp[512]; RMint32 i, j, x, n, nindexentries, indexoffset, tindexentries; tindexentries = chunk.Length / sizeof (AVI_INDEXENTRY); nindexentries = tindexentries; DEBUGMSG (1, ("%d index entries found\n", nindexentries)); RMuint32 videoFrameCount = 0; RMuint32 audioByteOrFrameCount[AVI_MAX_STREAMS_SUPPORTED]; for (i=0; i<AVI_MAX_STREAMS_SUPPORTED; i++) audioByteOrFrameCount[i] = 0; m_nIndexHelper = 0; x = 1; indexoffset = 0; while (nindexentries) { n = AVI_MIN (512, nindexentries); m_CallbackTable.fread (m_handle, tmp, sizeof(AVI_INDEXENTRY)*n, m_CallbackTable.context); for (i=0; i<n; i++) { if (((tmp[i].ckid & 0xffff0000) == 0x62640000) || ((tmp[i].ckid & 0xffff0000) == 0x63640000)) { if (videoFrameCount == 0) { DEBUGMSG (1, ("checking validity of chunk index ...\n")); // try to check if the index given is // relative to the start of the file or // if it is relative to the start of the movi chunk // the spec. says that it should be relative to the // start of the movi chunk. RMuint32 saved_position, tmpckid; saved_position = m_CallbackTable.ftell (m_handle, m_CallbackTable.context); m_CallbackTable.fseek (m_handle, tmp[i].dwChunkOffset, m_CallbackTable.context); m_CallbackTable.fread (m_handle, &tmpckid, sizeof(tmpckid), m_CallbackTable.context); DEBUGMSG (1, ("tmpckid = %08lx\n", tmpckid)); if (((tmpckid & 0xffff0000) == 0x62640000) || ((tmpckid & 0xffff0000) == 0x63640000)) { if (m_CallbackTable.info (AVI_DEMUX_MSG_INDEX_CHECK, 0, m_CallbackTable.context)) { DEBUGMSG (1, ("Assuming chunk indices are relative to the start of the file.\n")); m_IndexIsRelativeToStartOfFile = 1; } } m_CallbackTable.fseek (m_handle, saved_position, m_CallbackTable.context); } videoFrameCount++; if ((x == 1) && ((tmp[i].dwFlags & AVI_FLAGS_KEYFRAME) == 0)); else x--; } else if ((tmp[i].ckid & 0xffff0000) == 0x62770000) { RMuint32 idx = (((tmp[i].ckid & 0xff)-0x30) << 8) | (((tmp[i].ckid & 0xff00) >> 8)-0x30); if (idx < AVI_MAX_STREAMS_SUPPORTED) { if (m_vbrmp3[idx]) audioByteOrFrameCount[idx]++; else audioByteOrFrameCount[idx] += tmp[i].dwChunkLength; } } if (x == 0) { m_IndexHelper[m_nIndexHelper].indexOffset = indexoffset; m_IndexHelper[m_nIndexHelper].chunkOffset = tmp[i].dwChunkOffset; ASSERT ((RMint32)(videoFrameCount - 1) >= 0); m_IndexHelper[m_nIndexHelper].videoFrameCount = videoFrameCount - 1; for (j=0; j<AVI_MAX_STREAMS_SUPPORTED; j++) m_IndexHelper[m_nIndexHelper].audioByteOrFrameCount[j] = audioByteOrFrameCount[j]; x = ((m_avih.TotalFrames / AVI_MAX_INDEX_HELPER) + 1); m_nIndexHelper++; } indexoffset++; } nindexentries -= n; DEBUGMSG (1, ("%d index entries left\n", nindexentries)); ASSERT (m_CallbackTable.loading); m_CallbackTable.loading ((tindexentries - nindexentries) * 100 / tindexentries, m_CallbackTable.context); } } m_CallbackTable.fseek (m_handle, n + chunk.Length, m_CallbackTable.context); rifflength -= chunk.Length; break; default: DEBUGMSG (1, ("dump chunk = %c%c%c%c\n", chunk.Name >> 0, chunk.Name >> 8, chunk.Name >> 16, chunk.Name >> 24)); n = m_CallbackTable.ftell (m_handle, m_CallbackTable.context); m_CallbackTable.fseek (m_handle, n + chunk.Length, m_CallbackTable.context); rifflength -= chunk.Length; break; } ASSERT (m_CallbackTable.loading); } ASSERT (m_moviOffset < m_sizeOfFile); if (m_moviOffset == 0) { m_CallbackTable.fclose (m_handle, m_CallbackTable.context); m_handle = 0; DEBUGMSG (1, ("no 'movi' chunk found\n")); return AVI_DEMUX_ERROR_NOT_AN_AVI_FILE; } m_CallbackTable.fseek (m_handle, m_moviOffset, m_CallbackTable.context); m_demuxstate = AVI_DEMUX_STATE_CHUNK_NAME_BYTE0; m_savedbuf = 0; m_savedbuflen = 0; m_savedp = 0; return AVI_DEMUX_ERROR_NO_ERROR;}RMuint32 AVIDemux::CheckChunkId (){ if ((m_chunkid[2] == 'd') && (m_chunkid[3] == 'c')) { if ((m_chunkid[0] >= '0' && m_chunkid[0] <= '9') && (m_chunkid[1] >= '0' && m_chunkid[1] <= '9')) return 0; } if ((m_chunkid[2] == 'd') && (m_chunkid[3] == 'b')) { if ((m_chunkid[0] >= '0' && m_chunkid[0] <= '9') && (m_chunkid[1] >= '0' && m_chunkid[1] <= '9')) return 0; } if ((m_chunkid[2] == 'w') && (m_chunkid[3] == 'b')) { if ((m_chunkid[0] >= '0' && m_chunkid[0] <= '9') && (m_chunkid[1] >= '0' && m_chunkid[1] <= '9')) return 0; } // Divx Networks DRM info chunk if ((m_chunkid[2] == 'd') && (m_chunkid[3] == 'd')) { if ((m_chunkid[0] >= '0' && m_chunkid[0] <= '9') && (m_chunkid[1] >= '0' && m_chunkid[1] <= '9')) return 0; } // XXX I have never seen a 'JUNK' chunk if ((m_chunkid[0] == 'J') && (m_chunkid[1] == 'U') && (m_chunkid[2] == 'N') && (m_chunkid[3] == 'K')) return 0; // XXX ix## chunks are defined for open avi and are present // in the movi chunk if ((m_chunkid[0] == 'i') && (m_chunkid[1] == 'x')) { if ((m_chunkid[2] >= '0' && m_chunkid[2] <= '9') && (m_chunkid[3] >= '0' && m_chunkid[3] <= '9')) return 0; } // XXX idx1 chunks are sometimes at the end of the file if ((m_chunkid[0] == 'i') && (m_chunkid[1] == 'd') && (m_chunkid[2] == 'x') && (m_chunkid[3] == '1')) return 0; // XXX we do not support 'rec' chunks return 1;}AVI_DEMUX_ERROR AVIDemux::Schedule (){ ASSERT (m_moviOffset); RMuint8 *p, *buf; RMuint32 buflen, n; DEBUGMSG (0, ("AVIDemux::Schedule\n")); if (m_KeyFramesOnly) { return ScheduleKeyFramesOnly (); } if (m_demuxstate == AVI_DEMUX_STATE_RESTORE_STATE) { ASSERT (m_savedbuf); ASSERT (m_savedbuflen); ASSERT (m_savedp); p = m_savedp; buf = m_savedbuf; buflen = n = m_savedbuflen; m_demuxstate = m_savedstate; } else { if (m_CallbackTable.getbuffer (&p, &buflen, m_CallbackTable.context)) return AVI_DEMUX_ERROR_NO_BUFFER_AVAILABLE; n = m_CallbackTable.fread (m_handle, p, buflen, m_CallbackTable.context); if (n == 0) { return AVI_DEMUX_ERROR_FILE_DONE; } buflen = n; ASSERT (buflen < 0x80000000); ASSERT (m_demuxstate <= AVI_DEMUX_STATE_WRITE_CHUNK); ASSERT (m_CallbackTable.addref); buf = p; m_CallbackTable.addref (buf, m_CallbackTable.context); } while ((RMint32)buflen > 0) { switch (m_demuxstate) { case AVI_DEMUX_STATE_CHUNK_NAME_BYTE0: // chunk id byte 0 m_chunkid[0] = *p++; if (m_chunkid[0] != 0) m_demuxstate++; else m_demuxstate = AVI_DEMUX_STATE_CHUNK_NAME_BYTE0; buflen--; break; case AVI_DEMUX_STATE_CHUNK_NAME_BYTE1: // chunk id byte 1 m_chunkid[1] = *p++; m_demuxstate++; buflen--; break; case AVI_DEMUX_STATE_CHUNK_NAME_BYTE2: // chunk id byte 2 m_chunkid[2] = *p++; m_demuxstate++; buflen--; break; case AVI_DEMUX_STATE_CHUNK_NAME_BYTE3: // chunk id byte 3 m_chunkid[3] = *p++; m_demuxstate++; buflen--; // we should have the complete chunkid right now // try to verify that the chunk id is correct if (CheckChunkId ()) { // something is wrong // go back to state AVI_DEMUX_STATE_CHUNK_NAME_BYTE3 m_chunkid[0] = m_chunkid[1]; m_chunkid[1] = m_chunkid[2]; m_chunkid[2] = m_chunkid[3]; m_demuxstate = AVI_DEMUX_STATE_CHUNK_NAME_BYTE3; } else if ((m_chunkid[2] == 'd') && ((m_chunkid[3] == 'c') || (m_chunkid[3] == 'b'))) { m_currentFramePosition++; } break; case AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE0: // chunk length byte 0 m_chunklength = (RMuint32)*p++; m_demuxstate++; buflen--; break; case AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE1: // chunk length byte 1 m_chunklength |= (RMuint32)*p++ << 8; m_demuxstate++; buflen--; break; case AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE2: // chunk length byte 2 m_chunklength |= (RMuint32)*p++ << 16; m_demuxstate++; buflen--; break; case AVI_DEMUX_STATE_CHUNK_LENGTH_BYTE3: // chunk length byte 3 m_chunklength |= (RMuint32)*p++ << 24; m_bytecounter = 0; m_demuxstate++; buflen--; m_chunkstart = AVI_FLAG_CHUNK_START; // cheesy error detection if (m_chunklength >= m_sizeOfFile) { m_demuxstate = AVI_DEMUX_STATE_CHUNK_NAME_BYTE0; } if (m_chunklength == 0 || m_chunklength >= m_sizeOfFile) { m_CallbackTable.putChunk (m_chunkid, 0, 0, AVI_FLAG_CHUNK_END | m_chunkstart, m_CallbackTable.context); m_chunkstart = 0; } break; case AVI_DEMUX_STATE_WRITE_CHUNK: // send data if (m_bytecounter == m_chunklength) { m_savedbuf = buf; m_savedbuflen = buflen; m_savedp = p; m_savedstate = AVI_DEMUX_STATE_CHUNK_NAME_BYTE0; m_demuxstate = AVI_DEMUX_STATE_RESTORE_STATE; return AVI_DEMUX_ERROR_NO_ERROR; } if ((m_chunklength - m_bytecounter) < buflen) { RMuint32 chunklength = m_chunklength - m_bytecounter; ASSERT ((RMint32)chunklength >= 0); if (m_CallbackTable.putChunk (m_chunkid, p, chunklength, AVI_FLAG_CHUNK_END | m_chunkstart, m_CallbackTable.context) == 0) { m_chunkstart = 0; buflen -= chunklength; p += chunklength; m_bytecounter = m_chunklength; } else { // not tested ASSERT (0); m_savedbuf = buf; m_savedbuflen = buflen; m_savedp = p; m_savedstate = AVI_DEMUX_STATE_WRITE_CHUNK; m_demuxstate = AVI_DEMUX_STATE_RESTORE_STATE; return AVI_DEMUX_ERROR_NO_ERROR; } } else { if (m_CallbackTable.putChunk (m_chunkid, p, buflen, m_chunkstart, m_CallbackTable.context) == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -