📄 theoravidfmt.cpp
字号:
return res;}void CTheoraVideoFormat::Reset(){ DPRINTF(D_THEORA_VIDFMT, ("CTheoraVideoFormat::Reset()\n")); m_bNeedKeyframe = TRUE; m_lastFrameSize.cx = 0; m_lastFrameSize.cy = 0; ogg_stream_reset(&m_os); ogg_sync_reset(&m_oy); CVideoFormat::Reset();}void CTheoraVideoFormat::Close(){ HX_RELEASE(m_pStream); HX_RELEASE(m_pRegistry);}IHXBuffer* CTheoraVideoFormat::OggPktToIHXBuffer(ogg_packet* pOp){ UINT32 ulDataSize = sizeof(ogg_packet) + pOp->bytes; IHXBuffer* pRet = CreateBuffer(ulDataSize); if (pRet) { ogg_packet* pOggPkt = (ogg_packet*)pRet->GetBuffer(); UINT8* pPktData = pRet->GetBuffer() + sizeof(ogg_packet); // Copy ogg_packet struct *pOggPkt = *pOp; pOggPkt->packet = pPktData; // Copy packet data memcpy(pOggPkt->packet, pOp->packet, pOp->bytes); } return pRet;}CMediaPacket* CTheoraVideoFormat::CreateYUVPacket(theora_info* ti, yuv_buffer& yuv, UINT32 ulTimestamp){ CMediaPacket* pRet = NULL; if (yuv.y_width && yuv.y_height && (yuv.y_width == ti->width) && (yuv.y_height == ti->height) && (yuv.uv_width == ti->width / 2) && (yuv.uv_height == ti->height / 2)) { // We only handle 4:2:0 output from the decoder right now HXxSize* pDims = NULL; // The color converter only accepts frame widths that are // a multiple of 4. ti->frame_width should always be <= // ti->width and ti->width is always a multiple of 16. UINT32 uFrameWidth = (ti->frame_width + 3) & ~0x3; UINT32 uFrameHeight = ti->frame_height; UINT32 uAdjustedWidth = uFrameWidth; UINT32 uAdjustedHeight = uFrameHeight; UINT32 uXOffset = ti->offset_x; UINT32 uYOffset = ti->offset_y; BOOL bStrechX = FALSE; if (m_uAspectNum > m_uAspectDenom) { UINT32 uQ = uAdjustedWidth / m_uAspectDenom; UINT32 uR = uAdjustedWidth - uQ * m_uAspectDenom; uAdjustedWidth = (uQ * m_uAspectNum + (uR * m_uAspectNum) / m_uAspectDenom); uAdjustedWidth = (uAdjustedWidth + 3) & ~0x3; bStrechX = TRUE; if (!m_pPhaseInfo) { CreatePhaseInfo(m_uAspectNum); } } else if (m_uAspectNum < m_uAspectDenom) { UINT32 uQ = uAdjustedHeight / m_uAspectNum; UINT32 uR = uAdjustedHeight - uQ * m_uAspectNum; uAdjustedHeight = (uQ * m_uAspectDenom + (uR * m_uAspectDenom) / m_uAspectNum); if (!m_pPhaseInfo) { CreatePhaseInfo(m_uAspectDenom); } } UINT32 ulLumaSize = uAdjustedWidth * uAdjustedHeight; UINT32 ulChromaSize = ulLumaSize / 4; UINT32 ulFrameSize = ulLumaSize + 2 * ulChromaSize; if ((m_lastFrameSize.cx != uAdjustedWidth) || (m_lastFrameSize.cy != uAdjustedHeight)) { pDims = new HXxSize; if (pDims) { DPRINTF(D_THEORA_VIDFMT, ("CreateYUVPacket() : Setting frame size\n")); m_lastFrameSize.cx = uAdjustedWidth; m_lastFrameSize.cy = uAdjustedHeight; *pDims = m_lastFrameSize; } } pRet = GetMediaPacket(ulFrameSize, ulTimestamp, pDims); if (pRet) { UINT8* pData = pRet->m_pData; int lumaOffset = uXOffset + uYOffset * yuv.y_stride; int chromaOffset = (uXOffset / 2 + (uYOffset / 2) * yuv.uv_stride); if (m_pPhaseInfo) { // We are doing aspect ratio adjustment. if (bStrechX) { // We are stretching in the X direction // Copy and stretch Luma plane CopyAndStretchX(pData, yuv.y + lumaOffset, uFrameWidth, uFrameHeight, yuv.y_stride, m_uAspectNum, m_uAspectDenom, uAdjustedWidth, m_pPhaseInfo); // Copy and stretch first chroma plane CopyAndStretchX(pData, yuv.u + chromaOffset, uFrameWidth / 2, uFrameHeight / 2, yuv.uv_stride, m_uAspectNum, m_uAspectDenom, uAdjustedWidth / 2, m_pPhaseInfo); // Copy and stretch second chroma plane CopyAndStretchX(pData, yuv.v + chromaOffset, uFrameWidth / 2, uFrameHeight / 2, yuv.uv_stride, m_uAspectNum, m_uAspectDenom, uAdjustedWidth / 2, m_pPhaseInfo); } else { // We are stretching in the Y direction // Copy and stretch Luma plane CopyAndStretchY(pData, yuv.y + lumaOffset, uFrameWidth, uFrameHeight, yuv.y_stride, m_uAspectNum, m_uAspectDenom, uAdjustedHeight, m_pPhaseInfo); // Copy and stretch first chroma plane CopyAndStretchY(pData, yuv.u + chromaOffset, uFrameWidth / 2, uFrameHeight / 2, yuv.uv_stride, m_uAspectNum, m_uAspectDenom, uAdjustedHeight / 2, m_pPhaseInfo); // Copy and stretch second chroma plane CopyAndStretchY(pData, yuv.v + chromaOffset, uFrameWidth / 2, uFrameHeight / 2, yuv.uv_stride, m_uAspectNum, m_uAspectDenom, uAdjustedHeight / 2, m_pPhaseInfo); } } else { // Copy Luma plane CopyPixelData(pData, yuv.y + lumaOffset, uFrameWidth, uFrameHeight, yuv.y_stride); // Copy first chroma plane CopyPixelData(pData, yuv.u + chromaOffset, uFrameWidth / 2, uFrameHeight / 2, yuv.uv_stride); // Copy second chroma plane CopyPixelData(pData, yuv.v + chromaOffset, uFrameWidth / 2, uFrameHeight / 2, yuv.uv_stride); } } else { HX_DELETE(pDims); } } return pRet;}IHXBuffer* CTheoraVideoFormat::CreateBuffer(UINT32 ulSize){ IHXBuffer* pRet = NULL; if (m_pCommonClassFactory && (HXR_OK == m_pCommonClassFactory->CreateInstance(IID_IHXBuffer, (void**)&pRet)) && (HXR_OK != pRet->SetSize(ulSize))) { HX_RELEASE(pRet); } return pRet;}BOOL CTheoraVideoFormat::IsHeader(ogg_packet* pOp) const{ BOOL bRet = FALSE; if (pOp && pOp->packet && (pOp->bytes >= 7) && ((pOp->packet[0] & 0x80) == 0x80) && (!memcmp(pOp->packet + 1, "theora", 6))) { bRet = TRUE; } return bRet;}BOOL CTheoraVideoFormat::IsKeyframe(ogg_packet* pOp) const{ BOOL bRet = FALSE; if (pOp && pOp->packet && ((pOp->packet[0] & 0xc0) == 0)) { bRet = TRUE; } return bRet;}void CTheoraVideoFormat::HandleIdentHdr(ogg_packet* pOp){ if (IsHeader(pOp) && (pOp->bytes >= 42) && (pOp->packet[0] == 0x80)) { const unsigned char* pIdent = (const unsigned char*)pOp->packet; // Ident Header m_ulFPSNum = ((pIdent[0x16] << 24) | (pIdent[0x17] << 16) | (pIdent[0x18] << 8) | (pIdent[0x19])); m_ulFPSDenom = ((pIdent[0x1a] << 24) | (pIdent[0x1b] << 16) | (pIdent[0x1c] << 8) | (pIdent[0x1d])); // Attempt to reduce the numerator and denominator // by finding the greatest common denominator. UINT32 tmp = gcd(m_ulFPSNum, m_ulFPSDenom); if (tmp > 1) { m_ulFPSNum /= tmp; m_ulFPSDenom /= tmp; } }}UINT32 CTheoraVideoFormat::CalcTimestamp(UINT32 ulFrame) const{ UINT32 uRet = 0; if (m_ulFPSNum) { ogg_int64_t q = ulFrame / m_ulFPSNum; ogg_int64_t r = ulFrame - (q * m_ulFPSNum); ogg_int64_t mult = ((ogg_int64_t)m_ulFPSDenom) * 1000; ogg_int64_t ts = ((q * mult) + ((r * mult) / m_ulFPSNum)); uRet = INT64_TO_UINT32(ts); } return uRet;}void CTheoraVideoFormat::ChangeState(State newState){ DPRINTF(D_THEORA_VIDFMT, ("CTheoraVideoFormat::ChangeState() : %d -> %d\n", m_state, newState)); m_state = newState;}CMediaPacket* CTheoraVideoFormat::GetMediaPacket(UINT32 uFrameSize, UINT32 uTimestamp, HXxSize* pDims){ CMediaPacket* pRet = (CMediaPacket*)m_pFramePool->Get(uFrameSize); if (pRet) { pRet->Init(pRet->m_pData, uFrameSize, uTimestamp, 0, pDims); } else { UCHAR* pData = new UCHAR[uFrameSize]; if (pData) { pRet = new CMediaPacket(pData, pData, uFrameSize, uFrameSize, uTimestamp, 0, pDims /* desc */); if (!pRet) { HX_VECTOR_DELETE(pData); } } } if (pRet) { if (pDims) { pRet->SetSampleDescKiller(&DestroySampleDesc); } } return pRet;}void CTheoraVideoFormat::CreatePhaseInfo(UINT32 uPhaseCt){ m_pPhaseInfo = new UINT8[uPhaseCt]; if (m_pPhaseInfo) { for (UINT32 i = 0; i < uPhaseCt; i++) { m_pPhaseInfo[i] = (UINT8)MulDiv(256, i , uPhaseCt); } }}void CTheoraVideoFormat::updateBitrateInfo(theora_info* ti){ if (ti && m_pStream && m_pRegistry) { INT32 clipBitrate = ti->target_bitrate; UINT32 uStreamRegID; if (HXR_OK == getRegistryID(m_pStream, uStreamRegID)) { CHXString propName; if (HXR_OK == getPropName(uStreamRegID, "ClipBandwidth", propName)) { m_pRegistry->SetIntByName(propName, clipBitrate); } } }}void CTheoraVideoFormat::updateTACInfo(theora_comment* tc){ if (tc && m_pStream && m_pRegistry) { IHXStreamSource* pStreamSrc = NULL; UINT32 uSourceRegID; if ((HXR_OK == m_pStream->GetSource(pStreamSrc)) && (HXR_OK == getRegistryID(pStreamSrc, uSourceRegID))) { int tagInfoCount = sizeof(zm_tagInfo) / sizeof(TheoraTagMapping); for (int i = 0; i < tagInfoCount; i++) { char* pTheoraTag = zm_tagInfo[i].m_pTheoraTag; const char* pPropName = zm_tagInfo[i].m_pPropName; int commentCount = theora_comment_query_count(tc, pTheoraTag); if (commentCount > 0) { CHXString value = theora_comment_query(tc, pTheoraTag, 0); for (int j = 1; j < commentCount; j++) { value += ", "; value += theora_comment_query(tc, pTheoraTag, j); } IHXBuffer* pPropValBuf = NULL; if (HXR_OK == CreateStringBuffer(pPropValBuf, value, m_pCommonClassFactory)) { CHXString propName; if (HXR_OK == getPropName(uSourceRegID, pPropName, propName)) { m_pRegistry->SetStrByName(propName, pPropValBuf); } } HX_RELEASE(pPropValBuf); } } } HX_RELEASE(pStreamSrc); }}HX_RESULT CTheoraVideoFormat::getPropName(UINT32 uBaseID, const char* pChildPropName, CHXString& propName){ HX_RESULT res = HXR_INVALID_PARAMETER; if (!m_pRegistry) { res = HXR_UNEXPECTED; } else if (pChildPropName && strlen(pChildPropName)) { IHXRegistry* pReg = NULL; IHXBuffer* pBasePropName = NULL; res = m_pRegistry->GetPropName(uBaseID, pBasePropName); if (HXR_OK == res) { propName = (const char*)pBasePropName->GetBuffer(); propName += '.'; propName += pChildPropName; } HX_RELEASE(pBasePropName); } return res;}HX_RESULT CTheoraVideoFormat::getRegistryID(IUnknown* pUnk, REF(UINT32) uRegID){ HX_RESULT res = HXR_INVALID_PARAMETER; if (pUnk) { IHXRegistryID* pRegID = NULL; res = pUnk->QueryInterface(IID_IHXRegistryID, (void**)&pRegID); if (HXR_OK == res) { res = pRegID->GetID(uRegID); } HX_RELEASE(pRegID); } return res;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -