📄 avi.cpp
字号:
m_chunkstart = 0; m_bytecounter += buflen; p += buflen; buflen = 0; } 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; } } break; } } ASSERT (m_CallbackTable.release); m_CallbackTable.release (buf, m_CallbackTable.context); return AVI_DEMUX_ERROR_NO_ERROR;}#define AVI_DEMUX_KEYFRAMEONLY_STATE_NEXT_KEYFRAME 0#define AVI_DEMUX_KEYFRAMEONLY_STATE_PREV_KEYFRAME 1#define AVI_DEMUX_KEYFRAMEONLY_STATE_SEND_KEYFRAME 2#define AVI_DEMUX_KEYFRAMEONLY_STATE_DELAY 3#include <stdio.h>AVI_DEMUX_ERROR AVIDemux::ScheduleKeyFramesOnly (){ ASSERT (m_moviOffset); RMuint8 *p; RMuint32 buflen, n; RMint32 i; RMuint32 err; switch (m_KeyFrameOnlyState) { case AVI_DEMUX_KEYFRAMEONLY_STATE_NEXT_KEYFRAME: // get the next key frame for (i=m_CurrentIndex; i<m_IndexCacheValid; i++) { if (((m_IndexCache[i].ckid & 0xffff0000) == 0x62640000) || ((m_IndexCache[i].ckid & 0xffff0000) == 0x63640000)) { m_currentFramePosition++; if (m_IndexCache[i].dwFlags & AVI_FLAGS_KEYFRAME) { m_CurrentIndex = i + 1; if (m_IndexIsRelativeToStartOfFile) m_KeyFrameOffset = m_IndexCache[i].dwChunkOffset + 4; else m_KeyFrameOffset = m_moviOffset + m_IndexCache[i].dwChunkOffset + 4; m_KeyFrameLength = m_IndexCache[i].dwChunkLength; ASSERT ((RMint32)m_KeyFrameLength > 0); m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_DELAY; m_chunkid[0] = '0'; m_chunkid[1] = '0'; m_chunkid[2] = 'd'; m_chunkid[3] = 'c'; m_KeyFrameFlags = AVI_FLAG_CHUNK_START; m_CallbackTable.info (AVI_DEMUX_KEYFRAME_POSITION, (void *)(m_currentFramePosition - 1), m_CallbackTable.context); m_CallbackTable.fseek (m_handle, m_KeyFrameOffset, m_CallbackTable.context); break; } } } if (i == m_IndexCacheValid) { // reload index and try again m_IndexCacheOffset += (m_IndexCacheValid * sizeof (AVI_INDEXENTRY)); m_CallbackTable.fseek (m_handle, m_IndexCacheOffset, m_CallbackTable.context); n = m_CallbackTable.fread (m_handle, &m_IndexCache, sizeof (AVI_INDEXENTRY) * AVI_INDEX_CACHE_SIZE, m_CallbackTable.context); m_IndexCacheValid = n / sizeof (AVI_INDEXENTRY); m_CurrentIndex = 0; if ((m_IndexCacheValid == 0) || (m_IndexCacheOffset > (m_idx1Offset + m_idx1Length))) return AVI_DEMUX_ERROR_FILE_DONE; } break; case AVI_DEMUX_KEYFRAMEONLY_STATE_PREV_KEYFRAME: // get the previous key frame for (i=m_CurrentIndex; i>=0; i--) { if (((m_IndexCache[i].ckid & 0xffff0000) == 0x62640000) || ((m_IndexCache[i].ckid & 0xffff0000) == 0x63640000)) { m_currentFramePosition--; if (m_IndexCache[i].dwFlags & AVI_FLAGS_KEYFRAME) { m_CurrentIndex = i - 1; if (m_IndexIsRelativeToStartOfFile) m_KeyFrameOffset = m_IndexCache[i].dwChunkOffset + 4; else m_KeyFrameOffset = m_moviOffset + m_IndexCache[i].dwChunkOffset + 4; m_KeyFrameLength = m_IndexCache[i].dwChunkLength; ASSERT ((RMint32)m_KeyFrameLength > 0); m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_DELAY; m_chunkid[0] = '0'; m_chunkid[1] = '0'; m_chunkid[2] = 'd'; m_chunkid[3] = 'c'; m_KeyFrameFlags = AVI_FLAG_CHUNK_START; m_CallbackTable.info (AVI_DEMUX_KEYFRAME_POSITION, (void *)(m_currentFramePosition + 1), m_CallbackTable.context); m_CallbackTable.fseek (m_handle, m_KeyFrameOffset, m_CallbackTable.context); break; } } } if (i < 0) { // reload index cache and try again if (m_IndexCacheOffset == m_idx1Offset) return AVI_DEMUX_ERROR_FILE_DONE; m_IndexCacheOffset -= (sizeof (AVI_INDEXENTRY) * AVI_INDEX_CACHE_SIZE); if (m_IndexCacheOffset < m_idx1Offset) { m_CurrentIndex = AVI_INDEX_CACHE_SIZE - ((m_idx1Offset - m_IndexCacheOffset) / sizeof (AVI_INDEXENTRY)) - 1; ASSERT ((RMint32)m_CurrentIndex > 0); m_IndexCacheOffset = m_idx1Offset; ASSERT ((RMint32)m_IndexCacheOffset > 0); } else { ASSERT ((RMint32)m_IndexCacheOffset > 0); m_CurrentIndex = AVI_INDEX_CACHE_SIZE - 1; ASSERT ((RMint32)m_CurrentIndex > 0); } m_CallbackTable.fseek (m_handle, m_IndexCacheOffset, m_CallbackTable.context); n = m_CallbackTable.fread (m_handle, &m_IndexCache, sizeof (AVI_INDEXENTRY) * AVI_INDEX_CACHE_SIZE, m_CallbackTable.context); m_IndexCacheValid = n / sizeof (AVI_INDEXENTRY); } break; case AVI_DEMUX_KEYFRAMEONLY_STATE_SEND_KEYFRAME: if (m_CallbackTable.getbuffer (&p, &buflen, m_CallbackTable.context)) return AVI_DEMUX_ERROR_NO_BUFFER_AVAILABLE; n = AVI_MIN (buflen, m_KeyFrameLength); n = m_CallbackTable.fread (m_handle, p, n, m_CallbackTable.context); m_KeyFrameLength -= n; if (m_KeyFrameLength == 0) { DEBUGMSG (1, ("AVI_DEMUX_KEYFRAMEONLY_STATE_SEND_KEYFRAME: %d\n", (RMint32)m_currentFramePosition)); m_KeyFrameFlags |= AVI_FLAG_CHUNK_END; if (m_KeyFramesOnly > 0) m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_NEXT_KEYFRAME; else m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_PREV_KEYFRAME; ASSERT (m_CallbackTable.gettimems); m_KeyFrameDelay_t0 = m_CallbackTable.gettimems (m_CallbackTable.context); } err = m_CallbackTable.putChunk (m_chunkid, p, n, m_KeyFrameFlags, m_CallbackTable.context); // not allowed to pend only key frames ASSERT (err == 0); m_KeyFrameFlags = 0; break; case AVI_DEMUX_KEYFRAMEONLY_STATE_DELAY: i = m_CallbackTable.gettimems (m_CallbackTable.context); if ((RMint32)(i - m_KeyFrameDelay_t0) > m_KeyFrameDelayInMS) { m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_SEND_KEYFRAME; } break; } return AVI_DEMUX_ERROR_NO_ERROR;}AVI_DEMUX_ERROR AVIDemux::Seek (RMuint32 seconds, RMuint32 audiostreamno, RMuint32 *pvideoposition, RMuint32 *paudioposition, RMuint32 *paudiobyte){ RMuint32 i; RMuint32 s0, s1, Rate=24000, Scale=1000; if (m_idx1Offset == 0) { ASSERT (0); return AVI_DEMUX_ERROR_INVALID_PARAMETER; } ASSERT (audiostreamno < AVI_MAX_STREAMS_SUPPORTED); if (audiostreamno >= AVI_MAX_STREAMS_SUPPORTED) return AVI_DEMUX_ERROR_INVALID_PARAMETER; DEBUGMSG (1, ("AVI Seek (%d)\n", (RMint32)seconds)); for (i=0; i<AVI_MAX_STREAMS_SUPPORTED; i++) { if (AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[i], fccType) == AVI_FOURCC ('v','i','d','s')) { Rate = AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[i], Rate); Scale = AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[i], Scale); DEBUGMSG (1, (" Rate: %lu\n", AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[i], Rate))); DEBUGMSG (1, (" Scale: %lu\n", AVI_PACKED_STRUCTURE_ACCESS (m_StreamHeaders[i], Scale))); break; } } for (i=0; i<m_nIndexHelper-1; i++) { s0 = m_IndexHelper[i].videoFrameCount * Scale / Rate; s1 = m_IndexHelper[i+1].videoFrameCount * Scale / Rate; if ((seconds >= s0) && (seconds <s1)) { DEBUGMSG (1, (" videoFrameCount: %lu\n", m_IndexHelper[i].videoFrameCount)); DEBUGMSG (1, (" audioByteOrFrameCount: %lu\n", m_IndexHelper[i].audioByteOrFrameCount[audiostreamno])); DEBUGMSG (1, (" vbrmp3: %lu\n", m_vbrmp3[audiostreamno])); RMuint32 offset; if (m_IndexIsRelativeToStartOfFile) offset = m_IndexHelper[i].chunkOffset; else offset = m_moviOffset + m_IndexHelper[i].chunkOffset - 4; DEBUGMSG (1, (" seek to fileposition %lu.\n", offset)); m_CallbackTable.fseek (m_handle, offset, m_CallbackTable.context); m_demuxstate = AVI_DEMUX_STATE_CHUNK_NAME_BYTE0; *pvideoposition = m_IndexHelper[i].videoFrameCount; *paudioposition = m_IndexHelper[i].audioByteOrFrameCount[audiostreamno]; if (m_vbrmp3[audiostreamno]) *paudiobyte = 0; else *paudiobyte = 1; m_currentFramePosition = m_IndexHelper[i].videoFrameCount; DEBUGMSG (1, (" seek ok.\n")); return AVI_DEMUX_ERROR_NO_ERROR; } } DEBUGMSG (1, (" seek failed.\n")); return AVI_DEMUX_ERROR_INVALID_PARAMETER;}AVI_DEMUX_ERROR AVIDemux::KeyFramesOnly (RMint32 direction){ RMuint32 i, n; RMuint32 p0, p1; DEBUGMSG (1, ("AVIDemux::KeyFramesOnly (%d)\n", direction)); if (m_idx1Offset == 0) { ASSERT (0); return AVI_DEMUX_ERROR_INVALID_PARAMETER; } if (direction == 0) { m_KeyFramesOnly = 0; // continue normal demux from the current position m_CallbackTable.fseek (m_handle, m_KeyFrameOffset - 4, m_CallbackTable.context); return AVI_DEMUX_ERROR_NO_ERROR; } m_KeyFrameDelay_t0 = m_CallbackTable.gettimems (m_CallbackTable.context); RMuint32 currentpos = m_CallbackTable.ftell (m_handle, m_CallbackTable.context); m_KeyFrameOffset = currentpos + 4; DEBUGMSG (1, ("m_KeyFrameOffset = %d (%d + 4)\n", (RMint32)m_KeyFrameOffset, (RMint32)currentpos)); DEBUGMSG (1, ("m_nIndexHelper = %d\n", (RMint32)m_nIndexHelper)); DEBUGMSG (1, ("m_currentFramePosition = %d\n", (RMint32)m_currentFramePosition)); // find the nearest key frame for (i=0; i<m_nIndexHelper-1; i++) { if (m_IndexHelper[i].videoFrameCount) p0 = m_IndexHelper[i].videoFrameCount - 1; else p0 = 0; if (m_IndexHelper[i+1].videoFrameCount) p1 = m_IndexHelper[i+1].videoFrameCount - 1; else p1 = 0; DEBUGMSG (1, ("p0 = %d, p1 = %d\n", (RMint32)p0, (RMint32)p1)); if ((m_currentFramePosition >= p0) && (m_currentFramePosition < p1)) { // initialize the index cache m_KeyFramesOnly = direction; if (direction > 0) { m_IndexCacheOffset = m_idx1Offset + (m_IndexHelper[i].indexOffset * sizeof (AVI_INDEXENTRY)); m_CallbackTable.fseek (m_handle, m_IndexCacheOffset, m_CallbackTable.context); n = m_CallbackTable.fread (m_handle, &m_IndexCache, sizeof (AVI_INDEXENTRY) * AVI_INDEX_CACHE_SIZE, m_CallbackTable.context); m_IndexCacheValid = n / sizeof (AVI_INDEXENTRY); m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_NEXT_KEYFRAME; m_CurrentIndex = 0; } else { if (m_IndexHelper[i].indexOffset < AVI_INDEX_CACHE_SIZE) { m_IndexCacheOffset = m_idx1Offset; ASSERT ((RMint32)m_IndexCacheOffset >= 0); m_CurrentIndex = m_IndexHelper[i].indexOffset; ASSERT ((RMint32)m_CurrentIndex >= 0); } else { m_IndexCacheOffset = m_idx1Offset + (m_IndexHelper[i].indexOffset - AVI_INDEX_CACHE_SIZE) * sizeof (AVI_INDEXENTRY); ASSERT ((RMint32)m_IndexCacheOffset >= 0); m_CurrentIndex = AVI_INDEX_CACHE_SIZE - 1; ASSERT ((RMint32)m_CurrentIndex >= 0); } m_CallbackTable.fseek (m_handle, m_IndexCacheOffset, m_CallbackTable.context); n = m_CallbackTable.fread (m_handle, &m_IndexCache, sizeof (AVI_INDEXENTRY) * AVI_INDEX_CACHE_SIZE, m_CallbackTable.context); m_IndexCacheValid = n / sizeof (AVI_INDEXENTRY); m_KeyFrameOnlyState = AVI_DEMUX_KEYFRAMEONLY_STATE_PREV_KEYFRAME; } m_CallbackTable.fseek (m_handle, currentpos, m_CallbackTable.context); return AVI_DEMUX_ERROR_NO_ERROR; } } m_CallbackTable.fseek (m_handle, currentpos, m_CallbackTable.context); return AVI_DEMUX_ERROR_NO_KEYFRAME;}AVI_DEMUX_ERROR AVIDemux::GetFrame (RMuint32 frameno, RMuint8 *buffer, RMuint32 *length){ if (frameno) { ASSERT (0); return AVI_DEMUX_ERROR_NOT_IMPLEMENTED; } if (m_idx1Offset == 0) { ASSERT (0); return AVI_DEMUX_ERROR_INVALID_PARAMETER; } RMuint32 currentpos = m_CallbackTable.ftell (m_handle, m_CallbackTable.context); AVI_INDEXENTRY idx; m_CallbackTable.fseek (m_handle, m_idx1Offset, m_CallbackTable.context); while (1) { if (m_CallbackTable.fread (m_handle, &idx, sizeof(idx), m_CallbackTable.context) != sizeof(idx)) { ASSERT (0); m_CallbackTable.fseek (m_handle, currentpos, m_CallbackTable.context); return AVI_DEMUX_ERROR_INVALID_PARAMETER; } if (((idx.ckid & 0xffff0000) == 0x62640000) || ((idx.ckid & 0xffff0000) == 0x63640000)) { ASSERT (idx.dwFlags & AVI_FLAGS_KEYFRAME); if (m_IndexIsRelativeToStartOfFile) m_CallbackTable.fseek (m_handle, idx.dwChunkOffset, m_CallbackTable.context); else { ASSERT ((RMint32)(m_moviOffset + idx.dwChunkOffset - 4) > 0); m_CallbackTable.fseek (m_handle, m_moviOffset + idx.dwChunkOffset - 4, m_CallbackTable.context); } *length = AVI_MIN (*length, idx.dwChunkLength); *length = m_CallbackTable.fread (m_handle, buffer, *length, m_CallbackTable.context); break; } } m_CallbackTable.fseek (m_handle, currentpos, m_CallbackTable.context); return AVI_DEMUX_ERROR_NO_ERROR;}AVI_DEMUX_ERROR AVIDemux::SetKeyFrameDelay (RMuint32 delay_ms){ m_KeyFrameDelayInMS = delay_ms; return AVI_DEMUX_ERROR_NO_ERROR;}AVI_DEMUX_ERROR AVIDemux::IsStreamNumberVBR (RMuint32 audiostreamno, RMuint32 *is_vbr){ *is_vbr = m_vbrmp3[audiostreamno]; return AVI_DEMUX_ERROR_NO_ERROR;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -