zoukankan      html  css  js  c++  java
  • Intel Media SDK decode_sample剖析(二)——解码数据

    接上一篇:https://blog.csdn.net/y601500359/article/details/87260201

    接下来开始剖析数据解码函数:RunDecoding

    1. 初始化变量,不细说:

    2、下面while循环里是为了循环解码数据帧

    while (((sts == MFX_ERR_NONE) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) && (m_nFrames > m_output_count))
    
    {
        .........
    }

    3、接下来依次剖析while循环里面的代码行:

    (1)、在循环时,判断如果一旦输出解码数据(m_error = DeliverOutput(frame);)出错,立即跳出循环

    if (MFX_ERR_NONE != m_error) {
                msdk_printf(MSDK_STRING("DeliverOutput return error = %d
    "),m_error);
                break;
            }

    (2)、在文件播放是,如果数据帧不足一帧,读取下一部分数据:

     if (pBitstream && ((MFX_ERR_MORE_DATA == sts) || (m_bIsCompleteFrame && !pBitstream->DataLength))) {
                CAutoTimer timer_fread(m_tick_fread);
                sts = m_FileReader->ReadNextFrame(pBitstream); // read more data to input bit stream
    
                if (MFX_ERR_MORE_DATA == sts) {
                    sts = MFX_ERR_NONE;
                    // Timeout has expired or videowall mode
                    m_timer_overall.Sync();
                    if ( ((CTimer::ConvertToSeconds(m_tick_overall) < m_nTimeout) && m_nTimeout ) || m_bIsVideoWall)
                    {
                        m_FileReader->Reset();
                        m_bResetFileWriter = true;
                        continue;
                    }
    
                    // we almost reached end of stream, need to pull buffered data now
                    pBitstream = NULL;
                }

    (3)、同步数据表面:

    if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) {
                SyncFrameSurfaces();
                SyncVppFrameSurfaces();
                if (!m_pCurrentFreeSurface) {
                    m_pCurrentFreeSurface = m_FreeSurfacesPool.GetSurface();
                }
                if (!m_pCurrentFreeVppSurface) {
                  m_pCurrentFreeVppSurface = m_FreeVppSurfacesPool.GetSurface();
                }
    #ifndef __SYNC_WA
                if (!m_pCurrentFreeSurface || !m_pCurrentFreeVppSurface) {
    #else
                if (!m_pCurrentFreeSurface || (!m_pCurrentFreeVppSurface && m_bVppIsUsed) || (m_OutputSurfacesPool.GetSurfaceCount() == m_mfxVideoParams.AsyncDepth)) {
    #endif
                    // we stuck with no free surface available, now we will sync...
                    sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL);
                    if (MFX_ERR_MORE_DATA == sts) {
                        if ((m_eWorkMode == MODE_PERFORMANCE) || (m_eWorkMode == MODE_FILE_DUMP)) {
                            sts = MFX_ERR_NOT_FOUND;
                        } else if (m_eWorkMode == MODE_RENDERING) {
                            if (m_synced_count != m_output_count) {
                                sts = m_pDeliveredEvent->TimedWait(MSDK_DEC_WAIT_INTERVAL);
                            } else {
                                sts = MFX_ERR_NOT_FOUND;
                            }
                        }
                        if (MFX_ERR_NOT_FOUND == sts) {
                            msdk_printf(MSDK_STRING("fatal: failed to find output surface, that's a bug!
    "));
                            break;
                        }
                    }
                    // note: MFX_WRN_IN_EXECUTION will also be treated as an error at this point
                    continue;
                }
    
                if (!m_pCurrentFreeOutputSurface) 
                {
                    m_pCurrentFreeOutputSurface = GetFreeOutputSurface();
                }
                if (!m_pCurrentFreeOutputSurface) 
                {
                    sts = MFX_ERR_NOT_FOUND;
                    break;
                }
            }

    (4)、解码数据:并同步输出表面

     if ((MFX_ERR_NONE == sts) || (MFX_ERR_MORE_DATA == sts) || (MFX_ERR_MORE_SURFACE == sts)) {
                if (m_bIsCompleteFrame) 
                {
                    m_pCurrentFreeSurface->submit = m_timer_overall.Sync();
                }
                pOutSurface = NULL;
                do {
    #if (MFX_VERSION >= 1025)
                    if (pBitstream) {
                        pDecodeErrorReport = (mfxExtDecodeErrorReport *)GetExtBuffer(pBitstream->ExtParam, pBitstream->NumExtParam, MFX_EXTBUFF_DECODE_ERROR_REPORT);
                    }
    #endif
                    sts = m_pmfxDEC->DecodeFrameAsync(pBitstream, &(m_pCurrentFreeSurface->frame), &pOutSurface, &(m_pCurrentFreeOutputSurface->syncp));
    
    #if (MFX_VERSION >= 1025)
                    PrintDecodeErrorReport(pDecodeErrorReport);
    #endif
    
                    if (pBitstream && MFX_ERR_MORE_DATA == sts && pBitstream->MaxLength == pBitstream->DataLength)
                    {
                        mfxStatus stsExt = ExtendMfxBitstream(pBitstream, pBitstream->MaxLength * 2);
                        MSDK_CHECK_STATUS_SAFE(stsExt, "ExtendMfxBitstream failed", MSDK_SAFE_DELETE(pDeliverThread));
                    }
    
                    if (MFX_WRN_DEVICE_BUSY == sts) {
                        if (m_bIsCompleteFrame) {
                            //in low latency mode device busy leads to increasing of latency
                            //msdk_printf(MSDK_STRING("Warning : latency increased due to MFX_WRN_DEVICE_BUSY
    "));
                        }
                        mfxStatus _sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL);
                        // note: everything except MFX_ERR_NONE are errors at this point
                        if (MFX_ERR_NONE == _sts) {
                            sts = MFX_WRN_DEVICE_BUSY;
                        } else {
                            sts = _sts;
                            if (MFX_ERR_MORE_DATA == sts) {
                                // we can't receive MFX_ERR_MORE_DATA and have no output - that's a bug
                                sts = MFX_WRN_DEVICE_BUSY;//MFX_ERR_NOT_FOUND;
                            }
                        }
                    }
                } while (MFX_WRN_DEVICE_BUSY == sts);
    
                if (sts > MFX_ERR_NONE) {
                    // ignoring warnings...
                    if (m_pCurrentFreeOutputSurface->syncp) {
                        MSDK_SELF_CHECK(pOutSurface);
                        // output is available
                        sts = MFX_ERR_NONE;
                    } else {
                        // output is not available
                        sts = MFX_ERR_MORE_SURFACE;
                    }
                } else if ((MFX_ERR_MORE_DATA == sts) && pBitstream) {
                    if (m_bIsCompleteFrame && pBitstream->DataLength)
                    {
                        // In low_latency mode decoder have to process bitstream completely
                        msdk_printf(MSDK_STRING("error: Incorrect decoder behavior in low latency mode (bitstream length is not equal to 0 after decoding)
    "));
                        sts = MFX_ERR_UNDEFINED_BEHAVIOR;
                        continue;
                    }
                } else if ((MFX_ERR_MORE_DATA == sts) && !pBitstream) {
                    // that's it - we reached end of stream; now we need to render bufferred data...
                    do {
                        sts = SyncOutputSurface(MSDK_DEC_WAIT_INTERVAL);
                    } while (MFX_ERR_NONE == sts);
    
                    MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA);
                    if (sts) MSDK_PRINT_WRN_MSG(sts, "SyncOutputSurface failed")
    
                    while (m_synced_count != m_output_count) {
                        m_pDeliveredEvent->Wait();
                    }
                    break;
                } else if (MFX_ERR_INCOMPATIBLE_VIDEO_PARAM == sts) {
                    bErrIncompatibleVideoParams = true;
                    // need to go to the buffering loop prior to reset procedure
                    pBitstream = NULL;
                    sts = MFX_ERR_NONE;
                    continue;
                }
            }

    4、SyncOutputSurface函数:

    GetSurface:获取链表中的显示表面

    SyncOperation:此函数启动执行尚未启动的异步函数,并在指定的异步操作完成之后返回状态码。 如果wait为零,则函数立即返回。注:SyncOperation这个函数要特别注意,因为我在使用时发现部分电脑,在使用该函数时,返回MFX_ERR_UNKNOWN,最后查明原因,操作系统驱动问题,更新到最新后,正常了。

    5、DeliverOutput函数:

    该函数主要功能是输出,如果是保存文件模式,怎保存yuv数据到文件;如果是渲染模式,则通过D3D渲染。

    保存文件:注意是I420格式,Intel media sdk默认解码出来的是NV12格式,WriteNextFrameI420函数里面会进行一个NV12转I420。

            if (m_eWorkMode == MODE_FILE_DUMP) {
                res = m_pGeneralAllocator->Lock(m_pGeneralAllocator->pthis, frame->Data.MemId, &(frame->Data));
                if (MFX_ERR_NONE == res) {
                    res = m_bOutI420 ? m_FileWriter.WriteNextFrameI420(frame)
                        : m_FileWriter.WriteNextFrame(frame);
                    sts = m_pGeneralAllocator->Unlock(m_pGeneralAllocator->pthis, frame->Data.MemId, &(frame->Data));
                }
                if ((MFX_ERR_NONE == res) && (MFX_ERR_NONE != sts)) {
                    res = sts;
                }
            } 

    渲染模式:需要注意的是,里面的while循环,这个循环必须要,否则渲染的视频画面会出现时快时慢。

    else if (m_eWorkMode == MODE_RENDERING) {
    #if D3D_SURFACES_SUPPORT
                res = m_d3dRender.RenderFrame(frame, m_pGeneralAllocator);
    #elif LIBVA_SUPPORT
                res = m_hwdev->RenderFrame(frame, m_pGeneralAllocator);
    #endif
    
                while( m_delayTicks && (m_startTick + m_delayTicks > msdk_time_get_tick()) )
                {
                    MSDK_SLEEP(0);
                };
                m_startTick=msdk_time_get_tick();
            }

    sample就先简要剖析到此。下一篇开始进行实际项目运用。

  • 相关阅读:
    ubuntu-虚拟机跟主机资源共享的实现方法
    git- 仓库创建、修改、提交、撤销
    theme- 工作原理
    makeMtk- user 版本编译
    Button- 自定义控件添加自定义属性
    actionMode
    screen-Orientation 横竖屏设置
    worktools-mmx 添加编译模块
    eclipse- MAT安装及使用
    worktools-monkey 测试工具的使用
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049101.html
Copyright © 2011-2022 走看看