1. 程式人生 > >將各種格式flv,avi,mp4等的檔案,轉碼成MP4(無音訊)

將各種格式flv,avi,mp4等的檔案,轉碼成MP4(無音訊)

/*
 * test14.cpp
 *
 * 將各種格式flv,mp4的檔案,轉碼成MP4
 */

#include <string.h>
#include <math.h>
#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(&param, "preset", "slow", 0); av_dict_set(&param, "tune", "zerolatency", 0); //av_dict_set(&param, "profile", "main", 0); } //H.265 if(pCodecCtx->codec_id == AV_CODEC_ID_H265){ av_dict_set(&param, "preset", "ultrafast", 0); av_dict_set(&param, "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,&param) < 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; }