IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

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

    jsh13417发表于 2014-11-20 22:17:16
    love 0
    利用ffmpeg截取视频播放文件数据并保存为yuv格式。代码完全参考了这个链接的文章,很详细,在centos进行编译完全没有问题 。看下面的代码吧:/*File : testYuv.c *Auth : sjin *Date : 20141120 *Mail : 413977243@qq.com */ #include avformat.h> #include <libavcodecavcodec.h> #include avutil.h> #include <libavutilparseutils.h> int main(int argc, char *argv[]) { const char *szInfile = "BeatIt.mp4"; const char *szStartTime = "00:1:55.179"; const char *szEndTime = "00:4:20.110"; unsigned int i; int j = 0, k = 0; int width, height; int videoStream = -1; AVFormatContext *pFmtCtx = NULL; AVCodecContext *pCodecCtx = NULL; AVCodec *pCodec = NULL; AVFrame *pFrame = NULL; AVPacket packet; int getframe; AVRational avR, avTimeUint; AVDictionary *optionsDict = NULL; FILE *pFile; char szFilename[32]; double lframeRate; int64_t lStartTime, lEndTime; //millisecond(毫秒)=1/1000 s int64_t pos; int iStartFrame, iEndFrame; int isFirst = 1;//is the first keyframe(the frame av_seek_frame finds) av_register_all(); //convert time string "hh:mm:ss.xxx" to millisecond if (av_parse_time(&lStartTime;, szStartTime, 1) < 0) //lStartTime now in microsecond(1/1000 000 s) { printf("parse start time error!\n"); return -1; } pos = lStartTime; lStartTime /= 1000; if (av_parse_time(&lEndTime;, szEndTime, 1) < 0) { printf("parse end time error!\n"); return -1; } lEndTime /= 1000; if(avformat_open_input(&pFmtCtx;, szInfile, NULL, NULL) != 0){ return -1; } if(avformat_find_stream_info(pFmtCtx, NULL) < 0){ return -1; } av_dump_format(pFmtCtx, 0, szInfile, 0); for(i=0; inb_streams; i++){ if(pFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){ //帧率 分子/分母 lframeRate = pFmtCtx->streams[i]->avg_frame_rate.num / pFmtCtx->streams[i]->avg_frame_rate.den; //时间基数 avTimeUint.den = pFmtCtx->streams[i]->time_base.den; avTimeUint.num = pFmtCtx->streams[i]->time_base.num; width = pFmtCtx->streams[i]->codec->width; height = pFmtCtx->streams[i]->codec->height; //calc start and end frame number iStartFrame = (int)(lStartTime * lframeRate / 1000 + 0.5); iEndFrame = (int)(lEndTime * lframeRate / 1000 + 0.5); printf("avTimeUint.den:%d,avTimeUint.num:%d\n",avTimeUint.den,avTimeUint.num); printf("lframeRate:%f,width:%d,height:%d,lStartTime:%d,lEndTime:%d,iStartFrame:%d,iEndFrame:%d\n", lframeRate,width,height,lStartTime,lEndTime,iStartFrame,iEndFrame); videoStream=i; break; } } if(videoStream==-1) return -1; //获得编解码器上下文句柄, pCodecCtx = pFmtCtx->streams[videoStream]->codec; // 查找音视频解码器 pCodec = avcodec_find_decoder(pCodecCtx->codec_id); if(pCodec == NULL){ printf("Codec not found!\n"); return -1; } // 打开解码器 if(avcodec_open2(pCodecCtx, pCodec, &optionsDict;) < 0) return -1; //保存解压后的帧数据 pFrame = avcodec_alloc_frame(); //打开保存YUV的文件 sprintf(szFilename, "output.yuv");//output file pFile = fopen(szFilename, "wb"); if(pFile == NULL) return -1; avR.num = 1; avR.den = AV_TIME_BASE; //视频时间定位(DTS解码时间戳,PTS显示时间戳) //返回定位到开始时间的时间基 pos = av_rescale_q(pos, avR, pFmtCtx->streams[videoStream]->time_base); //跳转到指定时间的视频时刻 if(av_seek_frame(pFmtCtx, videoStream, pos, AVSEEK_FLAG_BACKWARD) < 0) { printf("seek failed!\n"); return -1; } //情况缓存 avcodec_flush_buffers(pFmtCtx->streams[videoStream]->codec); while(av_read_frame(pFmtCtx, &packet;)>=0) { if(packet.stream_index == videoStream) { //解码 avcodec_decode_video2(pCodecCtx, pFrame, &getframe;, &packet;); if(getframe) { //save yuv to disk if(isFirst) { k = lframeRate * pFrame->pkt_pts * avTimeUint.num / avTimeUint.den; isFirst = 0; if(pFrame->pict_type == AV_PICTURE_TYPE_SP){ printf("is P frame .........\n"); } } if(k >= iStartFrame && k<= iEndFrame) { for(j=0; jdata[0] + j * pFrame->linesize[0], 1, width, pFile); for(j=0; j2; j++) fwrite(pFrame->data[1] + j * pFrame->linesize[1], 1, width2, pFile); for(j=0; j2; j++) fwrite(pFrame->data[2] + j * pFrame->linesize[2], 1, width2, pFile); } } k++; if(k > iEndFrame) break; } //Free the packet that was allocated by av_read_frame av_free_packet(&packet;); }//while printf("Resolution: %dx%d", width, height); fflush(pFile); fclose(pFile); //Free the YUV frame av_free(pFrame); //Close the codec avcodec_close(pCodecCtx); //Close the video file avformat_close_input(&pFmtCtx;); return 0; }参考资料:1、关于视频显示时间及PTS相关的知识


沪ICP备19023445号-2号
友情链接