FFmpeg SDK开发课程笔记(一):调用FFmpeg SDK对YUV视频序列进行编码
来源:互联网 发布:嗯淘宝网店教学视频 编辑:程序博客网 时间:2024/06/05 07:15
课程地址 http://edu.csdn.net/course/detail/2515/39428?auto_start=1
需要包含的头文件
#include <iostream>#include <stdio.h>#include "Error.h"extern "C"{ //#include<stdio.h> #include <stdint.h> #include <libavcodec/avcodec.h> #include <libavformat/avformat.h> #include <libavutil/avutil.h> #include<libavutil/imgutils.h> #include <libavutil/opt.h>}
Error.h
就是定义几个出错类型就可以了
/* * Error.h * * Created on: Aug 14, 2017 * Author: media */#ifndef ERROR_H_#define ERROR_H_#define IO_FILE_ERROR_READ_FAILED -1#define FF_ERROR_INIT_FAILED -10#define FF_ERROR_ENCODE_FAILED -11#endif /* ERROR_H_ */
定义相关的变量
注意以下均为全局变量
文件路径
const char *inputFileName = NULL;const char *outputFileName = NULL;FILE *pFin = NULL, *pFout = NULL;
视频信息
int frameWidth = 0 , frameHeight = 0;int bitRate = 0, frameToEncode = 0;
ffmpeg中相关的数据结构
AVCodec *codec = NULL;AVCodecContext *codecCtx = NULL;AVFrame *frame = NULL;AVPacket pkt;
处理命令行参数
argv分别为
- 输入文件路径
- 输出文件路径
- 视频宽度
- 视频高度
- 码率
- 需要编码的帧数
static int parse_input_paramaters(int argc, char **argv){ inputFileName=argv[1]; outputFileName=argv[2]; pFin=fopen(inputFileName, "rb+"); if(!pFin) { std::cout<<"Error in reading inputfile"<<std::endl; return IO_FILE_ERROR_READ_FAILED; } pFout=fopen(outputFileName, "wb+"); if(!pFout) { std::cout<<"Error in reading outputfile"<<std::endl; return IO_FILE_ERROR_READ_FAILED; } frameWidth = atoi(argv[3]); frameHeight = atoi(argv[4]); bitRate = atoi(argv[5]); frameToEncode = atoi(argv[6]); return 1;}
读取YUV数据
static int read_yuv_data(int color){ /* color = 0 : Y * color = 1 : U * color = 2 : V */ int color_height = color == 0 ? frameHeight : frameHeight/2; int color_width = color == 0 ? frameWidth : frameWidth/2; //这里是YUV420P的格式 int color_size=color_height*color_width; int color_stride=frame->linesize[color]; if(color_width == color_stride) //这种情况相当于frame->data放满了 { //fread_s(frame->data[color], color_size, 1, color_size, pFin); //LINUX下没有fread_s fread(frame->data[color], color_size, 1, pFin); /* fread函数原型:size_t fread(void* buff,size_t size,size_t count,FILE* stream)作用:从文件中读入数据到指定的地址中,ffpempeg里面的AVFrame->data[0,1,2]用于存储YUV数据,所以读到这里参数:第一个参数为接收数据的指针(buff),也即数据存储的地址第二个参数为单个元素的大小,即由指针写入地址的数据大小,注意单位是字节第三个参数为元素个数,即要读取的数据大小为size的元素个素第四个参数为提供数据的文件指针,该指针指向文件内部数据 */ } else //这种情况还需要对齐 { for(int row_idx=0; row_idx<color_height;row_idx++) { //fread_s(frame->data[color]+row_idx*color_stride,color_width,1,color_width,pFin); fread(frame->data[color]+row_idx*color_stride,color_width,1,pFin); } } return pkt.size;}
main 函数
int main(int argv,char **argc){ int got_packet = 0; if(parse_input_paramaters(argv,argc)>0) { std::cout<<"Input file:"<<inputFileName<<std::endl; std::cout<<"Output file:"<<outputFileName<<std::endl; std::cout<<"frameWidth:"<<frameWidth<<std::endl; std::cout<<"frameHeight:"<<frameHeight<<std::endl; std::cout<<"bitRate:"<<bitRate<<std::endl; std::cout<<"frameToEncode:"<<frameToEncode<<std::endl; } else { std::cout<<"Error in cmd line!"<<std::endl; return -1; }//处理argv完毕 {//这个大括号似乎是多余的 avcodec_register_all(); //寻找编码器 codec = avcodec_find_encoder(AV_CODEC_ID_H264); if(!codec) { return FF_ERROR_INIT_FAILED; } //创建AVCodecContext 结构体,这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息,参考http://blog.csdn.net/yuan892173701/article/details/8702333 codecCtx = avcodec_alloc_context3(codec); if(!codecCtx) { return FF_ERROR_INIT_FAILED; } codecCtx->width = frameWidth; codecCtx->height = frameHeight; codecCtx->bit_rate = bitRate; AVRational r = {1, 25}; //时间刻度是1/25 codecCtx->time_base = r; codecCtx->gop_size = 12; //the number of pictures in a group of pictures, or 0 for intra_only codecCtx->max_b_frames = 1; codecCtx->pix_fmt=AV_PIX_FMT_YUV420P; av_opt_set(codecCtx->priv_data,"preset","slow",0); //初始化一个视音频编解码器的AVCodecContext if(avcodec_open2(codecCtx, codec, NULL)<0) { return FF_ERROR_INIT_FAILED; } //分配AVFrame frame = av_frame_alloc(); if(!frame) { return FF_ERROR_INIT_FAILED; } frame->width = codecCtx->width; frame->height = codecCtx->height; frame->format = codecCtx->pix_fmt; if(av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, (AVPixelFormat)frame->format, 32)<0) { return FF_ERROR_INIT_FAILED; } } for(int frameIdx = 0; frameIdx <frameToEncode; frameIdx++) { //初始化AVPacket av_init_packet(&pkt); pkt.data=NULL; pkt.size=0; //把YUV数据写入frame->data里面 read_yuv_data(0); read_yuv_data(1); read_yuv_data(2); frame->pts = frameIdx; if(avcodec_encode_video2(codecCtx, &pkt, frame, &got_packet)<0) //avcodec_encodec_video2: AVFrame to AVPacket { std::cout<<"Error in encoding"<<std::endl; return FF_ERROR_ENCODE_FAILED; } if(got_packet) { std::cout<<"Write packet of frame "<<frameIdx<<",size "<<pkt.size<<std::endl; fwrite(pkt.data, 1, pkt.size, pFout); av_packet_unref(&pkt); } for(got_packet = 1;got_packet;) { if(avcodec_encode_video2(codecCtx, &pkt, NULL, &got_packet)<0) { std::cout<<"Error in encoding"<<std::endl; return FF_ERROR_ENCODE_FAILED; } if(got_packet) //有时候帧数据写完了AVPacket里面还有东西 { if(avcodec_encode_video2(codecCtx, &pkt, frame, &got_packet)<0) { std::cout<<"Write packet of size "<<pkt.size<<std::endl; fwrite(pkt.data, 1, pkt.size, pFout); av_packet_unref(&pkt); } } } } // fclose(pFin); fclose(pFout); //释放内存 avcodec_close(codecCtx); av_free(codecCtx); av_freep(frame->data[0]); av_frame_free(&frame); std::cout<<"success!"<<std::endl; return 0;}
阅读全文
0 0
- FFmpeg SDK开发课程笔记(一):调用FFmpeg SDK对YUV视频序列进行编码
- 【FFMpeg视频开发与应用基础】二、调用FFmpeg SDK对YUV视频序列进行编码
- 调用ffmpeg SDK对YUV视频序列进行编码
- 【FFMpeg视频开发与应用基础】三、调用FFmpeg SDK对H.264格式的视频压缩码流进行解码
- 【FFMpeg视频开发与应用基础】五、调用FFMpeg SDK封装音频和视频为视频文件
- 【FFMpeg视频开发与应用基础】七、 调用FFMpeg SDK实现视频水印
- 【FFMpeg视频开发与应用基础】八、 调用FFMpeg SDK实现视频缩放
- 【FFMpeg视频开发与应用基础】六、调用FFMpeg SDK实现视频文件的转封装
- ffmpeg开发--ffmpeg sdk下载
- FFMpeg SDK 开发手册
- FFMpeg SDK 开发手册
- FFMpeg SDK 开发手册
- ffmpeg SDK开发手册
- FFMPEG SDK开发手册
- ffmpeg SDK开发
- ffmpeg sdk 开发相关
- FFMPEG SDK 开发介绍
- FFMPEG SDK 开发介绍
- SpringBoot之thymeleaf(Q)
- Jvm内部锁机制总结
- UVA 10385——Duathlon(三分)
- Python中Function(函数)和methon(方法)
- Need to read
- FFmpeg SDK开发课程笔记(一):调用FFmpeg SDK对YUV视频序列进行编码
- asp用户登录笔记
- javascript原型链理解
- iOS中tcp+protobuf
- 模态窗口详解及各浏览器适配经验分享
- 8.25面试SLAM算法工程师总结
- VS2008 连接TFS的问题
- 1026
- Xcode Missing file的解决方案