使用ffmpeg dxva技术解码

ffmpeg中已经实现了使用dxva加速解码部分代码。但是要整合在自己的播放器中dxva相关管理代码没有实现。

以下笔者带大家去实现一个基于dxva的加速解码器。

由于文笔不好,主要以代码来说话,望见谅。


一:ffmpeg中实现的dxva解码相关代码介绍

ffmpeg已经实现了h264 h263 mpeg2 wmv3解码的相关代码。关键代码如下

dxva2_h264.c

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. AVHWAccel ff_h264_dxva2_hwaccel = {  
  2.     .name           = "h264_dxva2",  
  3.     .type           = AVMEDIA_TYPE_VIDEO,  
  4.     .id             = CODEC_ID_H264,  
  5.     .pix_fmt        = PIX_FMT_DXVA2_VLD,  
  6.     .start_frame    = start_frame,  
  7.     .decode_slice   = decode_slice,  
  8.     .end_frame      = end_frame,  
  9.     .priv_data_size = sizeof(struct dxva2_picture_context),  
  10. };  

dxva2_mpeg2.c

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. AVHWAccel ff_mpeg2_dxva2_hwaccel = {  
  2.     .name           = "mpeg2_dxva2",  
  3.     .type           = AVMEDIA_TYPE_VIDEO,  
  4.     .id             = CODEC_ID_MPEG2VIDEO,  
  5.     .pix_fmt        = PIX_FMT_DXVA2_VLD,  
  6.     .start_frame    = start_frame,  
  7.     .decode_slice   = decode_slice,  
  8.     .end_frame      = end_frame,  
  9.     .priv_data_size = sizeof(struct dxva2_picture_context),  
  10. };  
dxva2_vc1.c

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #if CONFIG_WMV3_DXVA2_HWACCEL  
  2. AVHWAccel ff_wmv3_dxva2_hwaccel = {  
  3.     .name           = "wmv3_dxva2",  
  4.     .type           = AVMEDIA_TYPE_VIDEO,  
  5.     .id             = CODEC_ID_WMV3,  
  6.     .pix_fmt        = PIX_FMT_DXVA2_VLD,  
  7.     .start_frame    = start_frame,  
  8.     .decode_slice   = decode_slice,  
  9.     .end_frame      = end_frame,  
  10.     .priv_data_size = sizeof(struct dxva2_picture_context),  
  11. };  
  12. #endif  
  13.   
  14. AVHWAccel ff_vc1_dxva2_hwaccel = {  
  15.     .name           = "vc1_dxva2",  
  16.     .type           = AVMEDIA_TYPE_VIDEO,  
  17.     .id             = CODEC_ID_VC1,  
  18.     .pix_fmt        = PIX_FMT_DXVA2_VLD,  
  19.     .start_frame    = start_frame,  
  20.     .decode_slice   = decode_slice,  
  21.     .end_frame      = end_frame,  
  22.     .priv_data_size = sizeof(struct dxva2_picture_context),  
  23. };  

阅读上述代码,咱们会发现,解码器使用到的dxva_context没有复制,需要通过外部赋值

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. struct dxva_context {  
  2.     /** 
  3.      * DXVA2 decoder object 
  4.      */  
  5.     IDirectXVideoDecoder *decoder;  
  6.   
  7.     /** 
  8.      * DXVA2 configuration used to create the decoder 
  9.      */  
  10.     const DXVA2_ConfigPictureDecode *cfg;  
  11.   
  12.     /** 
  13.      * The number of surface in the surface array 
  14.      */  
  15.     unsigned surface_count;  
  16.   
  17.     /** 
  18.      * The array of Direct3D surfaces used to create the decoder 
  19.      */  
  20.     LPDIRECT3DSURFACE9 *surface;  
  21.   
  22.     /** 
  23.      * A bit field configuring the workarounds needed for using the decoder 
  24.      */  
  25.     uint64_t workaround;  
  26.   
  27.     /** 
  28.      * Private to the FFmpeg AVHWAccel implementation 
  29.      */  
  30.     unsigned report_id;  
  31. };  

在dxva2api.c(非ffmpeg的源码,由本人实现),中实现对转码的环境变量上下文进行赋值。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. static int Setup(va_dxva2_t *va, void **hw, const AVCodecContext *avctx)  
  2. {  
  3.     //va_dxva2_t *va = vlc_va_dxva2_Get(external);  
  4.     unsigned i;  
  5.       
  6.     if (va->width == avctx->width&& va->height == avctx->height && va->decoder)  
  7.         goto ok;  
  8.   
  9.     /* */  
  10.     DxDestroyVideoConversion(va);  
  11.     DxDestroyVideoDecoder(va);  
  12.   
  13.     *hw = NULL;  
  14.     if (avctx->width <= 0 || avctx->height <= 0)  
  15.         return -1;  
  16.   
  17.     if (DxCreateVideoDecoder(va, va->codec_id, avctx))  
  18.         return -1;  
  19.     /* */  
  20.     va->hw.decoder = va->decoder;  
  21.     va->hw.cfg = &va->cfg;  
  22.     va->hw.surface_count = va->surface_count;  
  23.     va->hw.surface = va->hw_surface;  
  24.     for (i = 0; i < va->surface_count; i++)  
  25.         va->hw.surface[i] = va->surface[i].d3d;  
  26.   
  27.     /* */  
  28.     DxCreateVideoConversion(va);  
  29.   
  30.     /* */  
  31. ok:  
  32.     *hw = &va->hw;  
  33.     const d3d_format_t *output = D3dFindFormat(va->output);  
  34.     //*chroma = output->codec;  
  35.     return 0;  
  36. }  

另外ffmpeg对阵硬解解码的环境变量赋值定义好了方式

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if(is->iUseDxva)  
  2.     {  
  3.         pCodecCtx->get_buffer = DxGetFrameBuf;  
  4.         pCodecCtx->reget_buffer = DxReGetFrameBuf;  
  5.         pCodecCtx->release_buffer = DxReleaseFrameBuf;  
  6.         pCodecCtx->opaque = NULL;  
  7.         //是否为需要硬解  
  8.         if(pCodecCtx->codec_id == CODEC_ID_MPEG1VIDEO || pCodecCtx->codec_id == CODEC_ID_MPEG2VIDEO ||  
  9.             //avctx->codec_id == CODEC_ID_MPEG4 ||  
  10.             pCodecCtx->codec_id == CODEC_ID_H264 ||  
  11.             pCodecCtx->codec_id == CODEC_ID_VC1 || pCodecCtx->codec_id == CODEC_ID_WMV3)  
  12.         {  
  13.             pCodecCtx->get_format = DxGetFormat;  
  14.         }  
  15.   
  16.             D3DXSaveSurfaceToFile = NULL;  
  17.         hdll = LoadLibrary(TEXT("D3DX9_42.DLL"));  
  18.         if(hdll)  
  19.             D3DXSaveSurfaceToFile =  (void *)GetProcAddress(hdll,TEXT("D3DXSaveSurfaceToFileA"));  
  20.     }  
  21.           
以下为dxva2硬解与ffmpeg接口实现的代码

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /***************************************************************************** 
  2.  * va.h: Video Acceleration API for avcodec 
  3.  ***************************************************************************** 
  4.  * Copyright (C) 2012 tuyuandong 
  5.  * 
  6.  * Authors: Yuandong Tu <tuyuandong@gmail.com> 
  7.  * 
  8.  * This file is part of FFmpeg.  
  9.  *****************************************************************************/  
  10. #include <libavutil/pixfmt.h>  
  11. #include <libavutil/pixdesc.h>  
  12. #include <libavcodec/avcodec.h>  
  13. #include <va.h>  
  14.   
  15. enum PixelFormat DxGetFormat( AVCodecContext *avctx,  
  16.                                           const enum PixelFormat *pi_fmt )  
  17. {  
  18.     unsigned int i;  
  19.     dxva_t *p_va = (dxva_t*)avctx->opaque;  
  20.   
  21.     if( p_va != NULL )  
  22.         dxva_Delete( p_va );  
  23.   
  24.     p_va = dxva_New(avctx->codec_id);  
  25.     if(p_va != NULL )  
  26.     {  
  27.         /* Try too look for a supported hw acceleration */  
  28.         for(i = 0; pi_fmt[i] != PIX_FMT_NONE; i++ )  
  29.         {  
  30.             const char *name = av_get_pix_fmt_name(pi_fmt[i]);  
  31.             av_log(NULL,AV_LOG_DEBUG, "Available decoder output format %d (%s)",  
  32.                      pi_fmt[i], name ? name : "unknown" );  
  33.             if( p_va->pix_fmt != pi_fmt[i] )  
  34.                 continue;  
  35.   
  36.             /* We try to call dxva_Setup when possible to detect errors when 
  37.              * possible (later is too late) */  
  38.             if( avctx->width > 0 && avctx->height > 0  
  39.              && dxva_Setup(p_va, &avctx->hwaccel_context,avctx) )  
  40.             {  
  41.                 av_log(NULL,AV_LOG_ERROR, "acceleration setup failure" );  
  42.                 break;  
  43.             }  
  44.   
  45.             //if( p_va->description )  
  46.             //    av_log(NULL,AV_LOG_INFO, "Using %s for hardware decoding.",  
  47.             //              p_va->description );  
  48.   
  49.             /* FIXME this will disable direct rendering 
  50.              * even if a new pixel format is renegotiated 
  51.              */  
  52.             //p_sys->b_direct_rendering = false;  
  53.             //p_sys->p_va = p_va;  
  54.             avctx->opaque = p_va;  
  55.             avctx->draw_horiz_band = NULL;             
  56.             return pi_fmt[i];  
  57.         }  
  58.   
  59.         av_log(NULL,AV_LOG_ERROR, "acceleration not available" );  
  60.         dxva_Delete( p_va );  
  61.     }  
  62.     avctx->opaque = NULL;  
  63.     /* Fallback to default behaviour */  
  64.     return avcodec_default_get_format(avctx, pi_fmt );  
  65. }  
  66.   
  67.   
  68. /***************************************************************************** 
  69.  * DxGetFrameBuf: callback used by ffmpeg to get a frame buffer. 
  70.  ***************************************************************************** 
  71.  * It is used for direct rendering as well as to get the right PTS for each 
  72.  * decoded picture (even in indirect rendering mode). 
  73.  *****************************************************************************/  
  74. int DxGetFrameBuf( struct AVCodecContext *avctx,  
  75.                                AVFrame *pic )  
  76. {  
  77.     dxva_t *p_va = (dxva_t *)avctx->opaque;  
  78.     //picture_t *p_pic;  
  79.   
  80.     /* */  
  81.     pic->reordered_opaque = avctx->reordered_opaque;  
  82.     pic->opaque = NULL;  
  83.   
  84.     if(p_va)  
  85.     {  
  86.         /* hwaccel_context is not present in old ffmpeg version */  
  87.         if( dxva_Setup(p_va,&avctx->hwaccel_context, avctx) )  
  88.         {  
  89.             av_log(NULL,AV_LOG_ERROR, "vlc_va_Setup failed" );  
  90.             return -1;  
  91.         }  
  92.   
  93.         /* */  
  94.         pic->type = FF_BUFFER_TYPE_USER;  
  95.   
  96. #if LIBAVCODEC_VERSION_MAJOR < 54  
  97.         pic->age = 256*256*256*64;  
  98. #endif  
  99.   
  100.         if(dxva_Get(p_va,pic ) )  
  101.         {  
  102.             av_log(NULL,AV_LOG_ERROR, "VaGrabSurface failed" );  
  103.             return -1;  
  104.         }  
  105.         return 0;  
  106.     }  
  107.   
  108.     return avcodec_default_get_buffer(avctx,pic );  
  109. }  
  110. int  DxReGetFrameBuf( struct AVCodecContext *avctx, AVFrame *pic )  
  111. {  
  112.     pic->reordered_opaque = avctx->reordered_opaque;  
  113.   
  114.     /* We always use default reget function, it works perfectly fine */  
  115.     return avcodec_default_reget_buffer(avctx, pic );  
  116. }  
  117.   
  118. void DxReleaseFrameBuf( struct AVCodecContext *avctx,  
  119.                                     AVFrame *pic )  
  120. {  
  121.     dxva_t *p_va = (dxva_t *)avctx->opaque;  
  122.     int i;  
  123.       
  124.     if(p_va )  
  125.     {  
  126.         dxva_Release(p_va, pic );  
  127.     }  
  128.     else if( !pic->opaque )  
  129.     {  
  130.         /* We can end up here without the AVFrame being allocated by 
  131.          * avcodec_default_get_buffer() if VA is used and the frame is 
  132.          * released when the decoder is closed 
  133.          */  
  134.         if( pic->type == FF_BUFFER_TYPE_INTERNAL )  
  135.             avcodec_default_release_buffer( avctx,pic );  
  136.     }  
  137.     else  
  138.     {  
  139.         //picture_t *p_pic = (picture_t*)p_ff_pic->opaque;  
  140.         //decoder_UnlinkPicture( p_dec, p_pic );  
  141.         av_log(NULL,AV_LOG_ERROR,"%d %s a error is rasied\e\n");  
  142.     }  
  143.     for(i = 0; i < 4; i++ )  
  144.         pic->data[i] = NULL;  
  145. }  
  146.   
  147. int DxPictureCopy(struct AVCodecContext *avctx,AVFrame *src, AVFrame* dst)  
  148. {  
  149.     dxva_t *p_va = (dxva_t *)avctx->opaque;  
  150.     return dxva_Extract(p_va,src,dst);  
  151. }  

demo实现的完整代码

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /***************************************************************************** 
  2.  * OnlyVideo.c: Video Decode Test 
  3.  ***************************************************************************** 
  4.  * Copyright (C) 2012 tuyuandong 
  5.  * 
  6.  * Authors: Yuandong Tu <tuyuandong@gmail.com> 
  7.  * 
  8.  * Data 2012-11-28 
  9.  * 
  10.  * This file is part of FFmpeg.  
  11.  *****************************************************************************/  
  12. #include <windows.h>  
  13. #include <d3d9.h>  
  14. #include <stdio.h>  
  15. #include "libavcodec/avcodec.h"  
  16. #include "libavformat/avformat.h"  
  17. #include "va.h"  
  18.   
  19. typedef struct VideoState {  
  20.     int     abort_request;  
  21.     char        filename[1024];  
  22.     int     srcWidth,srcHeight; //数据源大小  
  23.     int     iUseDxva;       //是否开启DXVA硬解  
  24. }VideoState;  
  25. char        out_path[128];  
  26.   
  27. void help();  
  28. DWORD VideoDecodec(LPVOID lpParameter);  
  29.   
  30. int main(int argc, char *argv[])  
  31. {  
  32.     VideoState is;  
  33.     int i;  
  34.     if(argc <2 || (argc == 2 && !strcmp(argv[1],"--help")))  
  35.     {  
  36.         help();  
  37.         return 0;  
  38.     }  
  39.   
  40.     memset(&is,0,sizeof(is));  
  41.     memset(out_path,0,sizeof(out_path));  
  42.     sprintf(is.filename,"%s",argv[1]);  
  43.     if(argc > 2 && !strcmp(argv[2],"-dxva"))  
  44.         is.iUseDxva = 1;      
  45.     if(argc >4  && !strcmp(argv[3],"-o"))  
  46.         strcpy(out_path,argv[4]);  
  47.       
  48.     if(out_path[0])  
  49.         CreateDirectory(out_path,NULL);  
  50.       
  51.     VideoDecodec(&is);  
  52.     return 0;  
  53. }  
  54.   
  55. void help()  
  56. {  
  57.     printf("**********************************************\n");  
  58.     printf("Usage:\n");  
  59.     printf("    OnlyVideo file [options]\n");  
  60.     printf("\n");  
  61.     printf("Options: \n");  
  62.     printf("    -dxva       \n");  
  63.     printf("    -o out_path\n");  
  64.     printf("\n");  
  65.     printf("Examples: \n");  
  66.     printf("    OnlyVideo a.mpg -dxva\n");  
  67.     printf("**********************************************\n");    
  68. }  
  69.   
  70. void console_log(const char *fmt, ...)  
  71. {  
  72.     HANDLE h;  
  73.     va_list vl;  
  74.     va_start(vl, fmt);  
  75.   
  76.     char buf[1024];  
  77.     memset(buf,0,1024);  
  78.     vsprintf(buf,fmt,vl);  
  79.   
  80.     h = GetStdHandle(STD_OUTPUT_HANDLE);  
  81.     COORD pos;  
  82.     ULONG unuse;  
  83.     pos.X= 0;  
  84.     CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息  
  85.     GetConsoleScreenBufferInfo(h, &bInfo );  
  86.     pos.Y= bInfo.dwCursorPosition.Y;  
  87.     WriteConsoleOutputCharacter(h,buf,strlen(buf),pos,&unuse);  
  88.       
  89.     va_end(vl);   
  90. }  
  91.   
  92.   
  93. typedef enum _D3DXIMAGE_FILEFORMAT  
  94. {  
  95.     D3DXIFF_BMP         = 0,  
  96.     D3DXIFF_JPG         = 1,  
  97.     D3DXIFF_TGA         = 2,  
  98.     D3DXIFF_PNG         = 3,  
  99.     D3DXIFF_DDS         = 4,  
  100.     D3DXIFF_PPM         = 5,  
  101.     D3DXIFF_DIB         = 6,  
  102.     D3DXIFF_HDR         = 7,       //high dynamic range formats  
  103.     D3DXIFF_PFM         = 8,       //  
  104.     D3DXIFF_FORCE_DWORD = 0x7fffffff  
  105.   
  106. } D3DXIMAGE_FILEFORMAT;  
  107.   
  108. void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {  
  109.     FILE *pFile;  
  110.     char szFilename[32];  
  111.     int  y;  
  112.   
  113.     // Open file  
  114.     if(out_path[0])  
  115.         sprintf(szFilename, ".\\%s\\frame%d.ppm",out_path, iFrame);  
  116.     else  
  117.         sprintf(szFilename, ".\\frame%d.ppm", iFrame);  
  118.       
  119.     pFile=fopen(szFilename, "wb");  
  120.     if(pFile==NULL)  
  121.         return;  
  122.   
  123.     // Write header  
  124.     fprintf(pFile, "P6\n%d %d\n255\n", width, height);  
  125.   
  126.     // Write pixel data  
  127.     for(y=0; y<height; y++)  
  128.         fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);  
  129.   
  130.     // Close file  
  131.     fclose(pFile);  
  132. }  
  133.   
  134. DWORD VideoDecodec(LPVOID lpParameter)  
  135. {  
  136. DWORD  (*D3DXSaveSurfaceToFile)(  
  137.         char*                    pDestFile,  
  138.         D3DXIMAGE_FILEFORMAT      DestFormat,  
  139.         LPDIRECT3DSURFACE9        pSrcSurface,  
  140.         CONST PALETTEENTRY*       pSrcPalette,  
  141.         CONST RECT*               pSrcRect);  
  142.   
  143.     VideoState*     is = lpParameter;  
  144.     AVFormatContext *pFormatCtx;  
  145.     int             i, videoStream;  
  146.     AVCodecContext  *pCodecCtx;  
  147.     AVCodec         *pCodec;  
  148.     AVFrame         *pFrame;   
  149.     AVFrame        *pFrameYUV = NULL;   
  150.     char*       pYUVBuf =NULL;  
  151.     AVPacket        pkt;  
  152.     int             frames;  
  153.     DWORD           dwTicks,cost;  
  154.     DWORD           sec;  
  155.     HINSTANCE   hdll = NULL;  
  156.   
  157.       
  158.     // Register all formats and codecs  
  159.     av_register_all();  
  160.   
  161.     // Open video file  
  162.     if(av_open_input_file(&pFormatCtx, is->filename, NULL, 0, NULL)!=0)  
  163.         return -1; // Couldn't open file  
  164.   
  165.       
  166.     // Retrieve stream information  
  167.     //if(av_find_stream_info(pFormatCtx)<0)  
  168.     //  return -1; // Couldn't find stream information  
  169.       
  170.     // Dump information about file onto standard error  
  171.     dump_format(pFormatCtx, 0, is->filename, 0);  
  172.   
  173.       
  174.     // Find the first video stream  
  175.     videoStream=-1;  
  176.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  177.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)  
  178.     {  
  179.         videoStream=i;  
  180.         break;  
  181.     }  
  182.       
  183.     if(videoStream==-1)  
  184.         return -1; // Didn't find a video stream  
  185.   
  186.     // Get a pointer to the codec context for the video stream  
  187.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;  
  188.   
  189.     pCodec=avcodec_find_encoder(CODEC_ID_H264);  
  190.   
  191.     // Find the decoder for the video stream  
  192.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);  
  193.     if(pCodec==NULL) {  
  194.         fprintf(stderr, "Unsupported codec!\n");  
  195.         return -1; // Codec not found  
  196.     }  
  197.   
  198.     if(is->iUseDxva)  
  199.     {  
  200.         pCodecCtx->get_buffer = DxGetFrameBuf;  
  201.         pCodecCtx->reget_buffer = DxReGetFrameBuf;  
  202.         pCodecCtx->release_buffer = DxReleaseFrameBuf;  
  203.         pCodecCtx->opaque = NULL;  
  204.         //是否为需要硬解  
  205.         if(pCodecCtx->codec_id == CODEC_ID_MPEG1VIDEO || pCodecCtx->codec_id == CODEC_ID_MPEG2VIDEO ||  
  206.             //avctx->codec_id == CODEC_ID_MPEG4 ||  
  207.             pCodecCtx->codec_id == CODEC_ID_H264 ||  
  208.             pCodecCtx->codec_id == CODEC_ID_VC1 || pCodecCtx->codec_id == CODEC_ID_WMV3)  
  209.         {  
  210.             pCodecCtx->get_format = DxGetFormat;  
  211.         }  
  212.   
  213.             D3DXSaveSurfaceToFile = NULL;  
  214.         hdll = LoadLibrary(TEXT("D3DX9_42.DLL"));  
  215.         if(hdll)  
  216.             D3DXSaveSurfaceToFile =  (void *)GetProcAddress(hdll,TEXT("D3DXSaveSurfaceToFileA"));  
  217.     }  
  218.           
  219.     // Open codec  
  220.     if(avcodec_open(pCodecCtx, pCodec)<0)  
  221.         return -1; // Could not open codec  
  222.   
  223.   
  224.     // Allocate video frame  
  225.     pFrame=avcodec_alloc_frame();  
  226.     pFrameYUV = avcodec_alloc_frame();  
  227.     if(pFrameYUV && is->iUseDxva)  
  228.     {  
  229.         int numBytes=avpicture_get_size(PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height);  
  230.         pYUVBuf=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));  
  231.         pFrameYUV->width = pCodecCtx->width;  
  232.         pFrameYUV->height =pCodecCtx->height;  
  233.         avpicture_fill((AVPicture *)pFrameYUV, pYUVBuf, PIX_FMT_YUV420P,pCodecCtx->width,pCodecCtx->height);  
  234.     }  
  235.       
  236.   
  237.     frames=0;  
  238.     cost = 0;  
  239.     sec = 0;  
  240.     while(!is->abort_request && av_read_frame(pFormatCtx, &pkt)>=0) {  
  241.         // Is this a packet from the video stream?  
  242.         if(pkt.stream_index==videoStream) {  
  243.             int got_picture;  
  244.             // Decode video frame  
  245.             dwTicks = GetTickCount();  
  246.             avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,&pkt);  
  247.             cost += (GetTickCount() - dwTicks);  
  248.               
  249.             // Did we get a video frame?  
  250.             if(got_picture) {     
  251.                 frames++;  
  252.                 if(cost/1000 > sec)  
  253.                 {  
  254.                     float speeds= (frames*1000.0)/cost;  
  255.                     console_log("pic_type[%d] frames[%d] times[%d] speeds[%f fps]\n",  
  256.                         pFrame->format,frames,cost,speeds);  
  257.                     sec ++;  
  258.   
  259.                     if(pFrame->format == PIX_FMT_DXVA2_VLD )  
  260.                     {  
  261.                         //char filename[256] = {0};  
  262.                         //DWORD ret = 0;  
  263.                         //LPDIRECT3DSURFACE9 d3d = pFrame->data[3];  
  264.                         //sprintf(filename,"e://%d.jpg",frames);  
  265.                         //if(D3DXSaveSurfaceToFile)  
  266.                         //  ret = D3DXSaveSurfaceToFile(filename,D3DXIFF_JPG/*jpeg*/,d3d,NULL,NULL);  
  267.                         //filename[128] =  0;  
  268.                         DxPictureCopy(pCodecCtx,pFrame,pFrameYUV);  
  269.                         SaveFrame(pFrameYUV,pFrameYUV->width,pFrameYUV->height,frames);  
  270.                     }  
  271.                 }  
  272.             }  
  273.         }  
  274.         // Free the packet that was allocated by av_read_frame  
  275.         av_free_packet(&pkt);  
  276.     }  
  277.   
  278.     avcodec_close(pCodecCtx);  
  279.     //av_close_input_file(pFormatCtx);  
  280.     if(pYUVBuf)  
  281.         av_free(pYUVBuf);  
  282.     if(pFrame)  
  283.         av_free(pFrame);  
  284.     if(pFrameYUV)  
  285.         av_free(pFrameYUV);  
  286.     if(hdll)  
  287.         FreeLibrary(hdll);  
  288. }  


可执行文件的下载

http://download.csdn.net/detail/tttyd/5166123


源代码下载

http://pan.baidu.com/share/link?shareid=703510495&uk=3240542740


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值