ffmprg Api 示例1--保存指定时间段的视频数据为yuv格式

来源:互联网 发布:梦想小镇绿钞淘宝 编辑:程序博客网 时间:2024/05/18 13:29

http://blog.csdn.net/sjin_1314/article/details/41323131

利用ffmpeg截取视频播放文件数据并保存为yuv格式。

代码完全参考了这个链接的文章,很详细,在centos进行编译完全没有问题 。

看下面的代码吧:

[cpp] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. /*File : testYuv.c 
  2.  *Auth : sjin 
  3.  *Date : 20141120 
  4.  *Mail : 413977243@qq.com 
  5.  */  
  6.   
  7. #include <libavformat/avformat.h>  
  8. #include <libavcodec/avcodec.h>  
  9. #include <libavutil/avutil.h>  
  10. #include <libavutil/parseutils.h>  
  11.   
  12.  int main(int argc, char *argv[])  
  13. {  
  14.     const char *szInfile = "BeatIt.mp4";  
  15.     const char *szStartTime = "00:1:55.179";  
  16.     const char *szEndTime = "00:4:20.110";  
  17.     unsigned int i;  
  18.     int j = 0, k = 0;  
  19.     int width, height;  
  20.     int videoStream = -1;  
  21.    
  22.     AVFormatContext *pFmtCtx = NULL;  
  23.     AVCodecContext  *pCodecCtx = NULL;  
  24.     AVCodec         *pCodec = NULL;  
  25.     AVFrame         *pFrame = NULL;  
  26.     AVPacket        packet;  
  27.     int             getframe;  
  28.     AVRational avR, avTimeUint;  
  29.     AVDictionary    *optionsDict = NULL;  
  30.    
  31.     FILE *pFile;  
  32.     char szFilename[32];  
  33.    
  34.     double  lframeRate;  
  35.     int64_t lStartTime, lEndTime; //millisecond(毫秒)=1/1000 s  
  36.     int64_t pos;  
  37.     int iStartFrame, iEndFrame;  
  38.     int isFirst = 1;//is the first keyframe(the frame av_seek_frame finds)  
  39.    
  40.     av_register_all();  
  41.    
  42.     //convert time string "hh:mm:ss.xxx" to millisecond  
  43.     if (av_parse_time(&lStartTime, szStartTime, 1) < 0) //lStartTime now in microsecond(1/1000 000 s)  
  44.     {  
  45.         printf("parse start time error!\n");  
  46.         return -1;  
  47.     }  
  48.     pos = lStartTime;  
  49.     lStartTime /= 1000;  
  50.    
  51.     if (av_parse_time(&lEndTime, szEndTime, 1) < 0)  
  52.     {  
  53.         printf("parse end time error!\n");  
  54.         return -1;  
  55.     }  
  56.     lEndTime /= 1000;  
  57.    
  58.     if(avformat_open_input(&pFmtCtx, szInfile, NULL, NULL) != 0){  
  59.         return -1;  
  60.     }  
  61.   
  62.     if(avformat_find_stream_info(pFmtCtx, NULL) < 0){  
  63.         return -1;  
  64.     }  
  65.   
  66.     av_dump_format(pFmtCtx, 0, szInfile, 0);  
  67.    
  68.     for(i=0; i<pFmtCtx->nb_streams; i++){  
  69.         if(pFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){  
  70.             //帧率  分子/分母  
  71.             lframeRate = pFmtCtx->streams[i]->avg_frame_rate.num / pFmtCtx->streams[i]->avg_frame_rate.den;  
  72.   
  73.             //时间基数  
  74.             avTimeUint.den = pFmtCtx->streams[i]->time_base.den;  
  75.             avTimeUint.num = pFmtCtx->streams[i]->time_base.num;  
  76.             width = pFmtCtx->streams[i]->codec->width;  
  77.             height = pFmtCtx->streams[i]->codec->height;  
  78.             //calc start and end frame number  
  79.             iStartFrame = (int)(lStartTime * lframeRate / 1000 + 0.5);   
  80.             iEndFrame = (int)(lEndTime * lframeRate / 1000 + 0.5);  
  81.   
  82.             printf("avTimeUint.den:%d,avTimeUint.num:%d\n",avTimeUint.den,avTimeUint.num);  
  83.             printf("lframeRate:%f,width:%d,height:%d,lStartTime:%d,lEndTime:%d,iStartFrame:%d,iEndFrame:%d\n",  
  84.                    lframeRate,width,height,lStartTime,lEndTime,iStartFrame,iEndFrame);  
  85.    
  86.             videoStream=i;  
  87.             break;  
  88.         }  
  89.     }  
  90.     if(videoStream==-1)  
  91.         return -1;  
  92.    
  93.     //获得编解码器上下文句柄,  
  94.     pCodecCtx = pFmtCtx->streams[videoStream]->codec;  
  95.    
  96.     // 查找音视频解码器  
  97.     pCodec = avcodec_find_decoder(pCodecCtx->codec_id);  
  98.     if(pCodec == NULL){  
  99.         printf("Codec not found!\n");  
  100.         return -1;  
  101.     }  
  102.     // 打开解码器  
  103.     if(avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0)  
  104.         return -1;  
  105.    
  106.     //保存解压后的帧数据  
  107.     pFrame = avcodec_alloc_frame();  
  108.    
  109.     //打开保存YUV的文件  
  110.     sprintf(szFilename, "output.yuv");//output file  
  111.     pFile = fopen(szFilename, "wb");  
  112.     if(pFile == NULL)  
  113.         return -1;  
  114.    
  115.     avR.num = 1;  
  116.     avR.den = AV_TIME_BASE;  
  117.    
  118.     //视频时间定位(DTS解码时间戳,PTS显示时间戳)  
  119.     //返回定位到开始时间的时间基  
  120.     pos = av_rescale_q(pos, avR, pFmtCtx->streams[videoStream]->time_base);  
  121.    
  122.     //跳转到指定时间的视频时刻  
  123.     if(av_seek_frame(pFmtCtx, videoStream, pos, AVSEEK_FLAG_BACKWARD) < 0)  
  124.     {  
  125.         printf("seek failed!\n");  
  126.         return -1;  
  127.     }  
  128.     //情况缓存  
  129.     avcodec_flush_buffers(pFmtCtx->streams[videoStream]->codec);  
  130.    
  131.     while(av_read_frame(pFmtCtx, &packet)>=0)  
  132.     {  
  133.         if(packet.stream_index == videoStream)  
  134.         {  
  135.             //解码  
  136.             avcodec_decode_video2(pCodecCtx, pFrame, &getframe, &packet);  
  137.             if(getframe)  
  138.             {  
  139.                 //save yuv to disk  
  140.                 if(isFirst)  
  141.                 {  
  142.                     k = lframeRate * pFrame->pkt_pts * avTimeUint.num / avTimeUint.den;  
  143.                     isFirst = 0;  
  144.                     if(pFrame->pict_type == AV_PICTURE_TYPE_SP){  
  145.                         printf("is P frame .........\n");  
  146.                     }  
  147.                 }  
  148.                 if(k >= iStartFrame && k<= iEndFrame)  
  149.                 {  
  150.                     for(j=0; j<height; j++)  
  151.                         fwrite(pFrame->data[0] + j * pFrame->linesize[0], 1, width, pFile);  
  152.                     for(j=0; j<height/2; j++)  
  153.                         fwrite(pFrame->data[1] + j * pFrame->linesize[1], 1, width/2, pFile);  
  154.                     for(j=0; j<height/2; j++)  
  155.                         fwrite(pFrame->data[2] + j * pFrame->linesize[2], 1, width/2, pFile);  
  156.                 }  
  157.    
  158.             }  
  159.             k++;  
  160.             if(k > iEndFrame)  
  161.                 break;  
  162.         }  
  163.         //Free the packet that was allocated by av_read_frame  
  164.         av_free_packet(&packet);  
  165.     }//while  
  166.    
  167.     printf("Resolution: %dx%d", width, height);  
  168.    
  169.     fflush(pFile);  
  170.     fclose(pFile);  
  171.     //Free the YUV frame  
  172.     av_free(pFrame);  
  173.     //Close the codec  
  174.     avcodec_close(pCodecCtx);  
  175.     //Close the video file  
  176.     avformat_close_input(&pFmtCtx);  
  177.     return 0;  
  178. }  

参考资料:1、关于视频显示时间及PTS相关的知识

0 0