需要的配置请参考:http://blog.csdn.net/geolo/article/details/48439747
/*
* test14.cpp
*
* 将各种格式flv,mp4的文件,转码成MP4
*/
#include
#include
#include "test06.h"
#define __STDC_CONSTANT_MACROS
int flush_encoder_14(AVFormatContext *fmt_ctx,unsigned int stream_index){
int ret;
int got_frame;
AVPacket enc_pkt;
if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
CODEC_CAP_DELAY))
return 0;
while (1) {
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2 (fmt_ctx->streams[stream_index]->codec, &enc_pkt,
NULL, &got_frame);
av_frame_free(NULL);
if (ret < 0)
break;
if (!got_frame){
ret=0;
break;
}
LOGE("Flush Encoder: Succeed to encode 1 frame!\tsize:%5d\n",enc_pkt.size);
/* mux encoded frame */
ret = av_write_frame(fmt_ctx, &enc_pkt);
if (ret < 0)
break;
}
return ret;
}
int Test14(){
LOGE("Test06 start \n");
AVFormatContext *mInFormatCtx;
AVCodecContext *mInCodecCtx;
AVCodec *mInCodec;
AVStream *mInStream;
AVFormatContext* pFormatCtx;
AVOutputFormat* fmt;
AVStream* video_st;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
AVPacket pkt;
uint8_t* picture_buf;
AVFrame* pFrame;
int picture_size;
int y_size;
int framecnt = 0;
char *mVideoFileName = "/sdcard/22.flv";
//FILE *in_file = fopen("src01_480x272.yuv", "rb"); //Input raw YUV data
FILE *in_file = fopen(mVideoFileName, "rb"); //Input raw YUV data
int in_w=480,in_h=272; //Input data's width and height
int framenum = 1000; //Frames to encode
//const char* out_file = "src01.h264"; //Output Filepath
//const char* out_file = "src01.ts";
//const char* out_file = "src01.hevc";
const char* out_file = "/sdcard/test14.mp4";
LOGE("Test06 run 01 \n");
av_register_all();
avcodec_register_all();
avformat_network_init();
//Method1.
pFormatCtx = avformat_alloc_context();
//Guess Format
fmt = av_guess_format(NULL, out_file, NULL);
pFormatCtx->oformat = fmt;
LOGE("Test06 run 02 \n");
//Method 2.
//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
//fmt = pFormatCtx->oformat;
AVCodec *_avcodecV = avcodec_find_encoder(AV_CODEC_ID_H264);
video_st = avformat_new_stream(pFormatCtx, _avcodecV);
//video_st->time_base.num = 1;
//video_st->time_base.den = 25;
LOGE("Test06 run 03 \n");
if (video_st==NULL){
LOGE("video_st==NULL \n");
return -1;
}
//Param that must set
pCodecCtx = video_st->codec;
pCodecCtx->flags |= CODEC_FLAG_QSCALE;
pCodecCtx->qmin = 0 ; //0是无损压缩。
pCodecCtx->qmax = 22 ; //20-30是比较合适的范围。
pCodecCtx->bit_rate = 0;
pCodecCtx->gop_size = 12;
pCodecCtx->width = in_w;
pCodecCtx->height = in_h;
pCodecCtx->time_base.num = 1;//分子
pCodecCtx->time_base.den = 25;//分母
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx->profile = FF_PROFILE_H264_BASELINE ;
pCodecCtx->max_b_frames = 0;
pCodecCtx->codec_id = fmt->video_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
//H264
// pCodecCtx->me_range = 16;
// pCodecCtx->max_qdiff = 4;
// pCodecCtx->qcompress = 0.6;
//Optional Param
if (fmt->flags & AVFMT_GLOBALHEADER){
pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
// Set Option
AVDictionary *param = 0;
//H.264
if(pCodecCtx->codec_id == AV_CODEC_ID_H264) {
av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
//av_dict_set(¶m, "profile", "main", 0);
}
//H.265
if(pCodecCtx->codec_id == AV_CODEC_ID_H265){
av_dict_set(¶m, "preset", "ultrafast", 0);
av_dict_set(¶m, "tune", "zero-latency", 0);
}
//Show some Information
av_dump_format(pFormatCtx, 0, out_file, 1);
LOGE("Test06 run 04 \n");
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec){
LOGE("Can not find encoder! \n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec,¶m) < 0){
LOGE("Failed to open encoder! \n");
return -1;
}
pFrame = av_frame_alloc();
picture_size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
picture_buf = (uint8_t *)av_malloc(picture_size);
avpicture_fill((AVPicture *)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
//Open output URL
if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
LOGE("Failed to open output file! \n");
return -1;
}
//Write File Header
avformat_write_header(pFormatCtx,NULL);
av_new_packet(&pkt,picture_size);
y_size = pCodecCtx->width * pCodecCtx->height;
LOGE("Test06 run 05 \n");
////// 解码部分 //////////////
mInFormatCtx = avformat_alloc_context();
if(avformat_open_input(&mInFormatCtx, mVideoFileName, NULL, NULL)!=0){
return -1;
}
if(avformat_find_stream_info(mInFormatCtx, NULL)<0){
return -1;
}
av_dump_format(mInFormatCtx, 0, mVideoFileName, 0);
LOGE("Test06 run 06 \n");
int videoStream;
videoStream = -1;
videoStream = av_find_best_stream(mInFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, &mInCodec, 0);
if(mInCodec == NULL) {
LOGE( "Unsupported pCodec!\n");
return -1; // Codec not found
}
mInCodecCtx = mInFormatCtx->streams[videoStream]->codec;
AVDictionary *optionsDict = NULL;
if(avcodec_open2(mInCodecCtx, mInCodec, &optionsDict)<0){
LOGE("---- 不能打开 视频 解码库 ---");
return -1;
}
LOGE("videoStream == %d \n", videoStream);
struct SwsContext *sws_ctx = NULL;
sws_ctx = sws_getContext(
mInCodecCtx->width,
mInCodecCtx->height,
mInCodecCtx->pix_fmt,
in_w,
in_h,
AV_PIX_FMT_YUV420P,
SWS_FAST_BILINEAR,
NULL, NULL, NULL);
AVFrame *mInFrame;
mInFrame = av_frame_alloc();
if(mInFrame == NULL){
LOGE("Failed to pFrameYUV==NULL ! \n");
return -1;
}
AVFrame *pFrameYUV;
pFrameYUV = av_frame_alloc();
int numBytes = avpicture_get_size(PIX_FMT_YUV420P, in_w, in_h);
uint8_t* buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameYUV, buffer, PIX_FMT_YUV420P,in_w, in_h);
LOGE("start encoder! \n");
//初始化SwsContext
SwsContext *rgbToyuvcxt = sws_getContext(
in_w,
in_h,
AV_PIX_FMT_RGB24,
in_w,
in_h,
AV_PIX_FMT_YUV420P,
SWS_POINT,
NULL,NULL,NULL);
AVFrame *m_pRGBFrame = av_frame_alloc(); //RGB帧数据
int rgbnumBytes = avpicture_get_size(AV_PIX_FMT_RGB24, in_w, in_h);
///////////////////////////////
for (int i=0; i < framenum; i++){
AVPacket packet;
if(av_read_frame(mInFormatCtx, &packet) >= 0 ){
if (packet.stream_index == videoStream) {
int completed;
avcodec_decode_video2(mInCodecCtx, mInFrame, &completed,&packet);// Decode video frame
sws_scale(
sws_ctx,
(uint8_t const * const *)mInFrame->data,
mInFrame->linesize,
0,
mInCodecCtx->height,
pFrameYUV->data,
pFrameYUV->linesize);
pFrame->data[0] = pFrameYUV ->data[0]; // Y
pFrame->data[1] = pFrameYUV ->data[1]; // U
pFrame->data[2] = pFrameYUV ->data[2]; // V
/**/
//PTS
//pFrame->pts = pFrameYUV-> pts;
//在编码前设置好,结果的pkt的配置
av_free_packet(&pkt);
av_init_packet(&pkt);
pkt.pts = framecnt;
pkt.dts = pkt.pts ;
//pkt.duration = 1;
int got_picture=0;
//Encode
int ret = avcodec_encode_video2(pCodecCtx, &pkt,pFrame, &got_picture);
if(ret < 0){
LOGE("Failed to encode! \n");
return -1;
}
if (got_picture == 1){
LOGE("Succeed to encode frame: %5d\t , size:%5d\n",framecnt,pkt.size);
//pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = video_st->index;
framecnt++;
ret = av_interleaved_write_frame(pFormatCtx, &pkt);
av_free_packet(&pkt);
}
}
}
}
//Flush Encoder
int ret = flush_encoder_14(pFormatCtx,0);
if (ret < 0) {
LOGE("Flushing encoder failed\n");
return -1;
}
//Write file trailer
av_write_trailer(pFormatCtx);
//Clean
if (video_st){
avcodec_close(video_st->codec);
av_free(pFrame);
av_free(picture_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(in_file);
return 0;
}