📄 rmasfdemux.cpp
字号:
/* trickmode related methods */RMstatus RMasfdemux::SetTrickModeDirection(RMint32 dir){ if ((dir != -1) && (dir != 1)) { RMDBGLOG((ENABLE, "Invalid direction(%ld)!\n", dir)); return RM_ERROR; } else { m_trickModeDirection = dir; if (dir > 0) RMDBGLOG((ENABLE, "trickmode direction set to forward\n")); else RMDBGLOG((ENABLE, "trickmode direction set to backward\n")); } return RM_OK;}RMuint64 RMasfdemux::SeekToTime(RMuint32 time_ms, RMuint32 *seekingToPacket, RMuint64 *seekingToTime){ RMuint64 entryNum; RMuint64 position; RMuint32 index; RMuint32 i; RMDBGLOG((ENABLE, "Seek to %lu ms\n", time_ms)); if (!m_isFileSeekable) { RMDBGLOG((ENABLE, "Ignoring, file is NOT seekable\n")); return 0; } if (time_ms >= (RMuint32)m_duration) { RMDBGLOG((ENABLE, "ERROR: trying to seek to %lu ms while reported duration is %llu, ignoring\n", time_ms, m_duration)); return 0; } if ((m_preroll) && (time_ms != 0)) { RMDBGLOG((ENABLE, ">> preroll(%llu) present, adjusting seek time to %lu\n", m_preroll, (RMuint32)m_preroll+time_ms)); time_ms = (RMuint32)m_preroll + time_ms; } if (m_isAudioOnly) { RMDBGLOG((ENABLE, "WMA audio only, using alternate seek\n")); return AlternateSeekToTime(time_ms, seekingToPacket, seekingToTime); } if ((!m_isThereAnIndex) || (!m_isIndexConstructed) || (m_numberOfIndex == 0)) { RMDBGLOG((ENABLE, "ERROR : no index\n")); return 0; } if (!m_localIndex) { RMDBGLOG((ENABLE, "ERROR: SeekToTime called without a locally constructed index\n")); return 0; } index = 0; // we use the first index by default entryNum = ((RMuint64)time_ms*10000UL)/m_simpleIndex[index].index_Entry_Time_Interval; if(entryNum > (RMuint64)m_simpleIndex[index].index_Entries_Count) { RMDBGLOG((ENABLE, "ERROR : entryNum (%llu) > max entry num (%lu)\n", entryNum, m_simpleIndex[index].index_Entries_Count)); return 0; } for (i = 0 ; i < (RMuint64)m_simpleIndex[index].index_Entries_Count ; i++) RMDBGLOG((DISABLE, "entry: %ld, packet %ld, count %d, pts %lld ms\n", (RMuint32)i, (RMuint32)m_simpleIndex[index].entry[i].Packet_Number, (RMint16)m_simpleIndex[index].entry[i].Packet_Count, (RMuint64)(i*m_simpleIndex[index].index_Entry_Time_Interval)/10000UL)); // header size + data object header size (fixed value) + packet position if((m_simpleIndex[index].entry != (typeSimpleIndexEntry*)NULL) && (time_ms > 0) && // When going to beginning, DO NOT enter seek mode because the first video Media Object will be skipped!!! (m_simpleIndex[index].entry[entryNum].Packet_Number > 0)){ position = m_header_Object_Size + 50 + ((RMuint64)m_simpleIndex[index].entry[entryNum].Packet_Number * (RMuint64)m_packetSize); *seekingToPacket = m_simpleIndex[index].entry[entryNum].Packet_Number; *seekingToTime = (RMuint64)time_ms; for (i = 0; i < (RMuint64)m_simpleIndex[index].index_Entries_Count; i++) { if (m_simpleIndex[index].entry[i].Packet_Number >= *seekingToPacket) { entryNum = i; break; } } *seekingToTime = (entryNum * m_simpleIndex[index].index_Entry_Time_Interval) / 10000UL; if (*seekingToTime > 1000) *seekingToTime -= 1000; else *seekingToTime = 0; RMDBGLOG((ENABLE, "Will seek to %lld ms, packet %ld\n", *seekingToTime, *seekingToPacket)); if (m_preroll) { *seekingToTime -= m_preroll; RMDBGLOG((ENABLE, ">>> adjusting to %llu due to preroll of %llu\n", *seekingToTime, m_preroll)); } } else { position = m_header_Object_Size + 50; *seekingToPacket = 1; *seekingToTime = (RMuint64)0; } RMDBGLOG((ENABLE, "Seek to position of entry %llu ... position = %llu, packet num = %lu\n", entryNum, position, *seekingToPacket)); return position;}RMuint64 RMasfdemux::AlternateSeekToTime(RMuint32 time_ms, RMuint32 *seekingToPacket, RMuint64 *seekingToTime){ RMuint32 timeSec = time_ms / 1000; RMuint32 seekPacket; RMuint64 seekPos; if (time_ms != 0) { seekPacket = (timeSec * m_audioBYTERate) / m_packetSize; if (seekPacket > m_packetCount) { RMDBGLOG((ENABLE, "alternateSeekToTime error, seekPacket(%lu) > packetCount(%lu)\n", seekPacket, m_packetCount)); return 0; } seekPos = m_header_Object_Size + 50 + (seekPacket * m_packetSize); if (seekPos < m_fileSize) { *seekingToPacket = seekPacket; *seekingToTime = time_ms; } else { RMDBGLOG((ENABLE, "alternateSeekToTime error, seekPos(%llu) > fileSize(%llu)\n", seekPos, m_fileSize)); return 0; } } else { seekPos = m_header_Object_Size + 50; *seekingToPacket = 1; *seekingToTime = (RMuint64)0; } RMDBGLOG((ENABLE, "alternate seektotime, pos %llu, packet %lu, time %lu s\n", seekPos, *seekingToPacket, timeSec)); return seekPos; }RMstatus RMasfdemux::InitTrickMode(RMuint64 *position){ RMuint64 entryNum = 0; RMuint64 entryValue; RMuint32 index; RMuint64 i; RMDBGLOG((TRICKMODEDBG, "InitTrickMode, position %llu\n", *position)); if (!m_isFileSeekable) { RMDBGLOG((ENABLE, "Ignoring, file is NOT seekable\n")); return RM_ERROR; } if (m_isAudioOnly) { RMDBGLOG((ENABLE, "audio only file, ignoring\n")); return RM_ERROR; } if ((!m_isThereAnIndex) || (!m_isIndexConstructed) || (m_numberOfIndex == 0)) { RMDBGLOG((ENABLE, "ERROR : no index\n")); return RM_ERROR; } if (!m_localIndex) { RMDBGLOG((ENABLE, "ERROR: InitTrickMode called without a locally constructed index\n")); return RM_ERROR; } m_ASFindexNum = 0; // we assume we will be using the first simple index. m_lastIFrame = 0; // reset last IFrame flag, used to detect EOS when in IFrame mode index = m_ASFindexNum; RMDBGLOG((ENABLE, "InitTrickMode: using index %ld\n", index)); entryValue = (*position - m_header_Object_Size - 50) / (RMuint64)m_packetSize; RMDBGLOG((ENABLE, "position %llu => packet %lu\n", *position, entryValue)); { /* count IFrames */ RMuint32 lastPacket = m_simpleIndex[index].entry[0].Packet_Number; RMuint32 IFrameNumber = 0; RMuint32 IFrameSeparation = 1; RMuint32 MaxIFrameSeparation = 0; for (i = 1 ; i < (RMuint64)m_simpleIndex[index].index_Entries_Count ; i++) { if (lastPacket != m_simpleIndex[index].entry[i].Packet_Number) { lastPacket = m_simpleIndex[index].entry[i].Packet_Number; IFrameNumber++; IFrameSeparation = 1; RMDBGLOG((TRICKMODEDBG, "Iframe %lu, pts %llu, packet %lu\n", IFrameNumber, (RMuint64)(i*m_simpleIndex[index].index_Entry_Time_Interval)/10000UL, lastPacket)); } else IFrameSeparation++; if (IFrameSeparation > MaxIFrameSeparation) MaxIFrameSeparation = IFrameSeparation; } RMDBGLOG((ENABLE, ">>> total IFrames %lu, mean time between Iframes %llu ms, MaxIFrameSeparation %lu ms\n", IFrameNumber, m_duration / (RMuint64)IFrameNumber, MaxIFrameSeparation * (m_simpleIndex[index].index_Entry_Time_Interval/10000UL))); } entryNum = (RMuint64) -1; for (i = 0 ; i < (RMuint64)m_simpleIndex[index].index_Entries_Count ; i++) RMDBGLOG((TRICKMODEDBG, "entry: %ld, packet %ld, count %d, pts %lld ms\n", (RMuint32)i, (RMuint32)m_simpleIndex[index].entry[i].Packet_Number, (RMint16)m_simpleIndex[index].entry[i].Packet_Count, (RMuint64)(i*m_simpleIndex[index].index_Entry_Time_Interval)/10000UL)); if (m_trickModeDirection == 0) { RMDBGLOG((ENABLE, "ERROR, direction is %ld!, must be positive for FFWD and negative for RWD\n", m_trickModeDirection)); return RM_ERROR; } if (m_trickModeDirection > 0) { RMDBGLOG((ENABLE, "ifwd: looking for nearest past iframe, to packet %llu\n", entryValue)); for (i = 0 ; i < (RMuint64)m_simpleIndex[index].index_Entries_Count ; i++) { if (m_simpleIndex[index].entry[i].Packet_Number >= entryValue) { entryNum = i; break; } } } else if (m_trickModeDirection < 0) { RMDBGLOG((ENABLE, "irwd: looking for nearest previous iframe, to packet %llu\n", entryValue)); for (i = (RMuint64)m_simpleIndex[index].index_Entries_Count - 1 ; i > 0 ; i--) { if (m_simpleIndex[index].entry[i].Packet_Number <= entryValue) { entryNum = i; break; } } } if (i != entryNum) { RMDBGLOG((ENABLE, "InitTrickMode: couldnt find nearest keyframe to position %lu!!!! trickmode will fail\n", (RMuint32)*position)); } else RMDBGLOG((ENABLE, "found: packet %lu\n", (RMuint32)m_simpleIndex[index].entry[entryNum].Packet_Number)); m_initentrynum = TRUE; if ((m_trickModeDirection > 0) || (m_trickModeDirection < 0)) { m_followingIFramePacket = m_simpleIndex[index].entry[entryNum].Packet_Number; m_followingIFramePacketSize = m_simpleIndex[index].entry[entryNum].Packet_Count * (RMuint64)m_packetSize; } else { RMDBGLOG((ENABLE, "ERROR, direction is %ld!, must be positive for FFWD and negative for RWD\n", m_trickModeDirection)); return RM_ERROR; } if(entryNum >= (RMuint64)m_simpleIndex[index].index_Entries_Count) { RMDBGLOG((ENABLE, "InitTrickMode ERROR : entryNum (%llu) > max entry num (%lu)\n", entryNum, m_simpleIndex[index].index_Entries_Count)); RMDBGLOG((ENABLE, "should start from the beggining or stop!\n")); entryNum = 0; *position = m_header_Object_Size + 50 + ((RMuint64)m_simpleIndex[index].entry[entryNum].Packet_Number * (RMuint64)m_packetSize); m_followingIFramePacket = m_simpleIndex[index].entry[entryNum].Packet_Number; m_followingIFramePacketSize = m_simpleIndex[index].entry[entryNum].Packet_Count * (RMuint64)m_packetSize; m_initentrynum = FALSE; return RM_ERROR; } // header size + data object header size (fixed value) + packet position if((m_simpleIndex[index].entry != (typeSimpleIndexEntry*)NULL) && (m_simpleIndex[index].entry[entryNum].Packet_Number > 0)) *position = m_header_Object_Size + 50 + ((RMuint64)m_simpleIndex[index].entry[entryNum].Packet_Number * (RMuint64)m_packetSize); else *position = m_header_Object_Size + 50; RMDBGLOG((ENABLE, "after InitTrickMode position is %llu\n", *position)); RMDBGLOG((ENABLE, "entry %llu, followingPacket %lu, followingSize %lu\n", entryNum, m_followingIFramePacket, m_followingIFramePacketSize)); return RM_OK;} RMstatus RMasfdemux::GetNextIFrame(RMuint64 *position){ RMuint64 entryNum = 0; RMuint32 index; RMuint64 i = 0; if (!m_isFileSeekable) { RMDBGLOG((ENABLE, "Ignoring, file is NOT seekable\n")); return RM_ERROR; } if (m_isAudioOnly) { RMDBGLOG((ENABLE, "audio only file, ignoring\n")); return RM_ERROR; } index = m_ASFindexNum; if (m_lastIFrame > 0) { if (m_trickModeDirection < 0) RMDBGLOG((ENABLE, ">>> IFrame FRWD EOS!\n")); else if (m_trickModeDirection > 0) RMDBGLOG((ENABLE, ">>> IFrame FFWD EOS!\n")); entryNum = 0; *position = m_header_Object_Size + 50 + ((RMuint64)m_simpleIndex[index].entry[entryNum].Packet_Number * (RMuint64)m_packetSize); m_followingIFramePacket = m_simpleIndex[index].entry[entryNum].Packet_Number; m_followingIFramePacketSize = m_simpleIndex[index].entry[entryNum].Packet_Count * (RMuint64)m_packetSize; return RM_EOS; } if (!m_initentrynum) { RMDBGLOG((ENABLE, "trickmodes non initialized!\n")); return RM_ERROR; } else { if (m_trickModeDirection > 0) { i = 0; while ((m_simpleIndex[index].entry[i].Packet_Number <= m_followingIFramePacket) && (i < m_simpleIndex[index].index_Entries_Count) ) { i++; } } else if (m_trickModeDirection < 0) { i = (RMuint64)m_simpleIndex[index].index_Entries_Count - 1; while ((m_simpleIndex[index].entry[i].Packet_Number >= m_followingIFramePacket) && ( i > 0 ) ) { i--; } } entryNum = i; RMDBGLOG((TRICKMODEDBG, "entry: %ld, packet %ld, count %d, pts %lld ms\n", (RMuint32)i, (RMuint32)m_simpleIndex[index].entry[i].Packet_Number, (RMint16)m_simpleIndex[index].entry[i].Packet_Count, (RMuint64)(i*m_simpleIndex[index].index_Entry_Time_Interval)/10000UL)); } if ((entryNum == 0) && (m_trickModeDirection < 0)) { RMDBGLOG((ENABLE, "reached last IFrame when in FRWD IFrame\n")); m_lastIFrame++; } if ((entryNum >= (RMuint64)m_simpleIndex[index].index_Entries_Count) && (m_trickModeDirection > 0)) { RMDBGLOG((ENABLE, "reached last IFrame when in FFWD IFrame\n")); m_lastIFrame++; entryNum = 0; *position = m_header_Object_Size + 50 + ((RMuint64)m_simpleIndex[index].entry[entryNum].Packet_Number * (RMuint64)m_packetSize); m_followingIFramePacket = m_simpleIndex[index].entry[entryNum].Packet_Number; m_followingIFramePacketSize = m_simpleIndex[index].entry[entryNum].Packet_Count * (RMuint64)m_packetSize; return RM_EOS; } m_followingIFramePacket = m_simpleIndex[index].entry[entryNum].Packet_Number; m_followingIFramePacketSize = m_simpleIndex[index].entry[entryNum].Packet_Count * (RMuint64)m_packetSize; // header size + data object header size (fixed value) + packet position if((m_simpleIndex[index].entry != (typeSimpleIndexEntry*)NULL) && (m_simpleIndex[index].entry[entryNum].Packet_Number > 0)) *position = m_header_Object_Size + 50 + ((RMuint64)m_simpleIndex[index].entry[entryNum].Packet_Number * (RMuint64)m_packetSize); else *position = m_header_Object_Size + 50; return RM_OK;}RMstatus RMasfdemux::GetNextIFrameSIZE(RMuint32 *size){ if (!m_initentrynum) { return RM_ERROR; } else { /* HACK! due to (bad?) A/V interleaving, sometimes the fragmented keyframe packets are non contiguous, that is, between them there are packets containing other streams. Given that we can't anticipate this situation, we have to read more packets than the index says. Twice as much seemed to work during tests */ /* had to change this to 4 times to fix bug #5954 */ *size = (RMuint32)m_followingIFramePacketSize * 4; return RM_OK; }}RMstatus RMasfdemux::GetNextIFramePacket(RMuint32 *packet){ if (!m_initentrynum) { return RM_ERROR; } else { *packet = (RMuint32)m_followingIFramePacket; return RM_OK; }}extern "C" void *RMASFDEMUXMOD__CreateInstance(void){ RMasfdemux *pdemux; pdemux = new RMasfdemux (); return (void *) pdemux;}#include "..
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -