[TOC]
循环读取视频帧
AVPacket packet = { 0 }; while (av_read_frame(m_pFmtCtx, &packet) >= 0) { if (m_videoIndex == packet.stream_index) { Decode(m_pDecoderCtx, &packet); av_packet_unref(&packet); } } // 缓冲中的可能还有数据,所以需要将剩下的数据一并解码 packet.data = NULL; packet.size = 0; Decode(m_pDecoderCtx, &packet); av_packet_unref(&packet);解码
两个重要的FFmpeg接口:
avcodec_send_packet,发送一个包给解码器;
avcodec_receive_frame,从解码器取回解码后的数据。
void Decode(AVCodecContext * pDecodeCtx, AVPacket * pPacket) { if (avcodec_send_packet(pDecodeCtx, pPacket) < 0) { return; } while (TRUE) { if (avcodec_receive_frame(pDecodeCtx, m_pFrame) != 0) { break; } DisplayVideo(m_pFrame); } }关于D3D显示的大概步骤是解码数据放在缓冲区,也就是这里离屏的概念,然后将离屏数据拷贝到后台缓冲表面,后台表面和前台表面不停的交替实现显示。
// 离屏 LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)pFrame->data[3]; // D3DCLEAR_TARGET 清除要渲染目标(帧缓存)的颜色为D3DCOLOR_XRGB(0, 0, 0)的值 // D3DCLEAR_ZBUFFER 清除深度缓冲(确定像素遮挡关系)的值为1.0f // D3DCLEAR_STENCIL 清除模板缓冲区(用于特效)为0 // 此时1.0f和0均会被忽略 m_pD3d9Dev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); m_pD3d9Dev->BeginScene(); IDirect3DSurface9 * pBackBuffer = nullptr; if (pBackBuffer) { pBackBuffer->Release(); pBackBuffer = NULL; } // 获取第1个交换链上的第一个后台缓冲区的地址 m_pD3d9Dev->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); GetClientRect(m_hWnd, &m_renderRect); // 将待显示的数据拷贝到后台缓冲区,通过线性插值的方式显示到指定窗口区域 m_pD3d9Dev->StretchRect(surface, NULL, pBackBuffer, &m_renderRect, D3DTEXF_LINEAR); m_pD3d9Dev->EndScene(); m_pD3d9Dev->Present(NULL, NULL, NULL, NULL); #if !CAMERA Sleep(1000 / m_frameRate); #endif转载于:https://www.cnblogs.com/huluwa508/p/10331525.html
相关资源:DXVA2解码数据用texture纹理渲染