void cMediaVideoPacket::Handle( cMedia* pMedia, void* pData ) { cProfileCPUSample sample( "cMediaVideoPacket::Handle" ); AVPacket* pPacket = (AVPacket *)pData; KBASSERT( !!pMedia && "cMediaVideoPacket::Handle() requires valid player" ); KBASSERT( !!pPacket && "cMediaVideoPacket::Handle() requires valid packet" ); AVCodecContext* pVideoCodecContext = (AVCodecContext *)pMedia->m_pVideoCodecContext; AVFormatContext* pFormatContext = (AVFormatContext *)pMedia->m_pSource->m_pFormatContext; AVFrame* pFrame = (AVFrame *)pMedia->m_pScratchVideoFrame; int nFrameFinished = 0; while ( pPacket->size > 0 ) { int nLength = 0; ProfileCPU( "cMediaVideoPacket::Handle [Decode]" ) { nLength = avcodec_decode_video2( pVideoCodecContext, (AVFrame *)pMedia->m_pScratchVideoFrame, &nFrameFinished, pPacket ); } if ( nLength < 0 ) { return; } if ( nFrameFinished ) { // allocate an output frame AVFrame* pResampledFrame = nullptr; if ( video_resampling ) { pResampledFrame = av_frame_alloc(); av_image_alloc( pResampledFrame->data, pResampledFrame->linesize, pVideoCodecContext->width, pVideoCodecContext->height, AV_PIX_FMT_YUV420P, 1 ); ProfileCPU( "cMediaVideoPacket::Handle [Scale]" ) { // scale from source format to target format while retaining size sws_scale( (struct SwsContext *)pMedia->m_pVideoResampler, (const unsigned char *const *)pFrame->data, pFrame->linesize, 0, pVideoCodecContext->height, pResampledFrame->data, pResampledFrame->linesize ); } } // get PTS kbFloat64 fPTS = 0.0; if ( pPacket->dts != AV_NOPTS_VALUE ) { fPTS = (kbFloat64)av_frame_get_best_effort_timestamp( (const AVFrame *)pMedia->m_pScratchVideoFrame ); fPTS *= av_q2d( pFormatContext->streams[ pMedia->m_pSource->m_nVideoStreamIndex ]->time_base ); } // Just seeked: set clock syncronize and position if ( pMedia->m_cSeekFlag == 1 ) { pMedia->m_fVideoClockPosition = fPTS; pMedia->m_fClockSync = pMedia->m_fTime - fPTS; pMedia->m_cSeekFlag = 0; } // lock and write to video buffer cMediaVideoPacket* pVideoPacket = Create( pMedia, (void *)( video_resampling ? pResampledFrame : pFrame ), fPTS ); kbBool bDone = false; pMedia->m_pVideoMutex->Lock(); if ( cMediaBuffer::Write( (cMediaBuffer *)pMedia->m_pVideoBuffer, pVideoPacket ) == 0 ) { bDone = true; } pMedia->m_pVideoMutex->Unlock(); // unable to write the packet: just drop it if ( !bDone ) { Free( pVideoPacket ); } } pPacket->size -= nLength; pPacket->data += nLength; } }