首页 > 编程知识 正文

ffmpeg转mp4格式,ffmpeg从入门到精通

时间:2023-05-04 08:58:56 阅读:115449 作者:1163

1视频解码的视频解码是通过对应的解码算法将经压缩视频(诸如H264的压缩格式)恢复为YUV视频流的过程; 在计算机看来,首先输入01个字符串(压缩视频),然后进行大量浮点运算,最后输出更长的01个字符串(恢复的未压缩视频)。 计算机内部可进行浮点计算的部件是CPU,目前市场上出现了几种Nvidia、雾度芯片,以及英特尔自己的核显示等GPU和GPU类芯片。 利用前者进行解码一般称为“软解码”,后者称为“硬解码”,如果没有特别指定,FFMPEG用CPU进行解码,即软解码。

源代码

//testYuv.cpp :此文件包含“main”函数。 程序的执行在此开始和结束。 //# define _ CRT _ secure _ no _ warnings # include stdio.h # include stdlib.h extern ' c ' { # include ' libavcodec _ s voidYUV420(constchar*path,int width,int height ) (file* ) (int width,int height ) ) file * f1=fopen (' YUV 422 ) file*F2=fopen('YUV420_u.y ',' wb ' ); file*F3=fopen('YUV420_v.y ',' wb ' ); 无符号char * p=(无符号char * ) malloc ) width*Height*3/2); int i=0; while(I750 ) fread(p,1,width*height * 3/2,fp ); 写入(p,1,width*height,f1 ); 写入(pwidth * height,1,width*height/4,f2 ); write(Pwidth*height*(1)1/4)、1,width*height/4,f3 ); I; }fclose(FP ); flose(F1; flose(F2; flose(F3; (}int main ) ) (/YUV420(11.YUV )、720、480 ); //注册所有组件av_register_all; const char* path='11.mp4 '; const char * output='test.yuv '; //包格式上下文,指挥全局结构并存储视频文件包格式信息的AVFormatContext *pFormat=NULL; //输入视频文件intret=av format _ open _ input (p format、path、NULL、NULL ); if(ret ) printf('%s”,“无法打开输入视频文件n”; 返回- 1; //3获取视频文件信息ret=av format _ find _ stream _ info (p format,NULL ); if(ret ) ) printf )、(av format _ find _ stream _ info failed (n ); 返回- 1; (}int time=pFormat-duration; int maxtime=time/av _ time _ base/60; intmintime=time/av_time_base `; printf (时间%d分%d秒)、maxtime、mintime ); av_dump_format(pformat,NULL,path,0 ); //获取视频流的索引位置//遍历所有类型的流(音频流、视频流、字幕流),视频流int视频流=-1,音频流videostream=av _ find _ best _ stream (p format,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,NULL ); /*以下方式为同av_find_best_streamfor(intI=0; i pFormat-nb_streams; I ) ) /流的类型if (p format-streams [ I ]-codec-codec _ type==av media _ type _ video ) {VideoStream=i; 布雷克; }}*///只要知道视频的编码方式,就可以根据编码方式找到解码器。 //视频流中的编解码器上下文avcodeccontext * pcodecctx=p format-streams [ videostream ]-codec; 找不到if(pcodecctx==null ) printf('%s ','解码器n ' ); 返回- 1; //4 .从编解码器上下文中的编码id中查找对应的解码av codec * pav code=av codec _ find _ decoder (pcodectx-codec _ id ); if (! pav代码(printf ) ) av

codec_find_decoder failedn");return -1;}//5. 打开解码器 注意新库和老库都用avcodec_open2if (avcodec_open2(pCodecCtx, pAvCode, NULL) < 0){printf("%s", "解码器无法打开n");return -1;}//输出视频信息printf("视频的文件格式:%sn", pFormat->iformat->name);printf("视频时长:%d秒n", (pFormat->duration) / 1000000);printf("视频的宽高:%d,%dn", pCodecCtx->width, pCodecCtx->height);printf("解码器的名称:%sn", pAvCode->name);//准备读取//AVPacket用于存储一帧一帧的压缩数据(H264)//缓冲区,开辟空间AVPacket* packet = (AVPacket*)av_malloc(sizeof(AVPacket));//AVFrame用于存储解码后的像素数据(YUV)//内存分配AVFrame* pFrame = av_frame_alloc();//YUV 420AVFrame* pFrameYUV = av_frame_alloc();//缓冲区分配内存uint8_t *out_buffer = (uint8_t*)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));//初始化缓冲区 一帧图像avpicture_fill((AVPicture *)pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//用于转码(缩放)的参数,转之前的宽高,转之后的宽高,格式等struct SwsContext *sws_ctx =sws_getContext(pCodecCtx->width, pCodecCtx->height,pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,SWS_BICUBIC, NULL, NULL, NULL);int got_picture;int width = pCodecCtx->width;int height = pCodecCtx->height;int frame_count = 0;FILE *fp_yuv = fopen(output, "wb+");FILE* fy = fopen("11_yuv_y.y", "wb+");FILE* fu = fopen("11_yuv_u.y", "wb+");FILE* fv = fopen("11_yuv_v.y", "wb+");// 6.一帧一帧的读取压缩数据while (av_read_frame(pFormat, packet) >= 0){if (packet->stream_index == AVMEDIA_TYPE_VIDEO){//7.解码一帧视频压缩数据,得到视频像素数据ret = avcodec_decode_video2(pFormat->streams[VideoStream]->codec, pFrame, &got_picture, packet);if (ret < 0){printf(" avcodec_decode_video2 failedn");return -1;}//为0说明解码完成,非0正在解码if (got_picture){//AVFrame转为像素格式YUV420,宽高 //2 6输入、输出数据 //3 7输入、输出画面一行的数据的大小 AVFrame 转换是一行一行转换的 //4 输入数据第一列要转码的位置 从0开始 //5 输入画面的高度sws_scale(sws_ctx,(const uint8_t**)pFrame->data,pFrame->linesize,0,pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);//输出到YUV文件 //AVFrame像素帧写入文件 //data解码后的图像像素数据(音频采样数据) //Y 亮度 UV 色度(压缩了) 人对亮度更加敏感 //U V 个数是Y的1/4fwrite(pFrameYUV->data[0], 1, width*height, fp_yuv);fwrite(pFrameYUV->data[1], 1, width*height / 4, fp_yuv);fwrite(pFrameYUV->data[2], 1, width*height / 4, fp_yuv);fwrite(pFrameYUV->data[0], 1, width*height, fy);fwrite(pFrameYUV->data[1], 1, width*height / 4, fu);fwrite(pFrameYUV->data[2], 1, width*height / 4, fv);frame_count++;printf("解码第%d帧n", frame_count);}}}fclose(fp_yuv);fclose(fy);fclose(fu);fclose(fv);sws_freeContext(sws_ctx);av_frame_free(&pFrame);av_frame_free(&pFrameYUV);avformat_close_input(&pFormat);return 0;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。