SD平台,由于内存限制,解码HD节目将出现内存崩溃的问题。
要解决该问题,应该在解码前判断出HD节目,阻止解码过程,并且通知上层应用以便提示用户该节目为高清节目,不能解码。
方法如下,请注意红色修改部分:
1. in phStbAV_callbacks.c function phStbAv_OnNewSequenceFound()
… … …
status = tmdlMsvdGetSequenceInfo (pInstance->msvdInstance,
&seqInfo );
if (status == TM_OK)
{
/* If new seq header then see if we have to deal with the changes or not.*/
if((seqInfo.seqHeight != pInstance->seqInfo.seqHeight) ||
(seqInfo.seqWidth != pInstance->seqInfo.seqWidth) ||
(seqInfo.aspectRatio != pInstance->seqInfo.aspectRatio) ||
(seqInfo.pictureRate != pInstance->seqInfo.pictureRate) ||
(seqInfo.tvStandard != pInstance->seqInfo.tvStandard)
#ifndef CONFIG_HDDECODE_ENABLE
||((seqInfo.seqHeight > 576) || (seqInfo.seqWidth > 720))
/* Force seqInfo change to inform the application that this format is not supported */
#endif
)
{
… …
//通知视频流变化信息
/* seqInfo has changed.*/
*pUpdated = true;
}
}
2. 应用程序的处理
应用程序在得到DVPET_STREAMCHANGE事件后,停止音视频并且提示用户不能解码。在我们DVB-T的参考代码中,处理方法如下:
文件DirectFBManager.cpp函数DirectFBManager_eventThread()
static void DirectFBManager_eventThread(void *pArg)
… … …
case DVPET_STREAMCHANGE:
#ifndef CONFIG_HDDECODE_ENABLE
/* If service is HD, whereas we are on SD only configuration */
if (gfx_videoProvider[which].streamDescription.video.width > 720)
{
/* Stop the videoprovider */
if (eventsInfo.videoprovider.data_type == DVPEDST_VIDEO)
{
TRACE_INFO(("Sending StartFailed\n"));
/* Report that video has not started */
video_handle[MAIN_VIDEO_DEVICE].callback_func(video_handle[MAIN_VIDEO_DEVICE].callback_user_data,
/* Notify the playback thread, check will be made inside the function */
PlaybackThread_notifyVideoStarted();
}
if (eventsInfo.videoprovider.data_type == DVPEDST_AUDIO)
{
/* Report that audio has just started */
audio_handle[MAIN_VIDEO_DEVICE].callback_func(audio_handle[MAIN_VIDEO_DEVICE].callback_user_data);
/* Notify the playback thread, check will be made inside the function */
PlaybackThread_notifyAudioStarted();
}
}
#endif
… … …
callback_func()的处理参考见最后。
3. MSVD部分处理,作为自我保护,MSVD在判断到节目为高清节目而平台为标清配置的时候,需要自动停止解码。过程如下:
A. in phddMsvd2Lisr.c, 函数sf_Msvd2Lisr_ProcessEOPH()处理Msvd中断事件时。如果发现不支持高清解码,则调用相应处理过程。
… … …
/* Check Resolution */
eResError = phddMsvd2_Lctx_CheckHDEnable(
tPictureEventData.tPictureDisplay.usDispHor,
tPictureEventData.tPictureDisplay.usDispVer ); //判断是否为高清节目而高清解码是否打开
if( eResError == phddMsvd2_Ldec_ErrorNotSupported )
{
/* Can not decode a HD stream with a SD firmware */
/* change state */
gphddMsvd2_Lctx.tDec[ulHandle].eDecState = phddMsvd2_Ldec_StateError;
gphddMsvd2_Lctx.tDec[ulHandle].eDecSubState = phddMsvd2_Lctx_SubStateNo;
/* send back fatal error */
tEventData = phddMsvd2_Ldec_ErrorFatalFormatNotSupported;
gphddMsvd2_Lctx.tDec[ulHandle].pfCallback(
ulHandle,
PHDD_MSVD2LDEC_EVENT_FATAL_ERROR,
(phddMsvd2_Ldec_EventData_t*)&tEventData );
}
B. 文件tmdlMsvdPrivate.c函数tmdlMsvd_DEC_callback()处理该事件,并通知相应MSVD任务处理,处理如下:
case phddMsvd2_Hdec_ErrorFatalFormatNotSupported:
{
/* Send an event to the monitor task. */
(void)tmdlMsvdPrivate_SendMessage(
tmdlMsvd_MessageType_Stop,
msvdInstance,
0, NULL);
}
break;
C. 文件tmdlMsvdPrivate.c函数MsvdPrivate_MonitorTask()
该任务得到tmdlMsvd_MessageType_Stop后,停止Msvd解码
case tmdlMsvd_MessageType_Stop:
MsvdPrivate_Stop(msg.instance);
break;
注:我们的客户再处理此类问题时,并不需要涉及到底层部分的修改,只要参考第二节提到的应用程序部分的处理即可。尽管底层进行了自我保护,如果应用程序不停掉音视频,以便下次重启该过程,解码过程将无法恢复。
其实还可以更详细