編譯ffmpeg(第一次),實現JPG轉MP4


ffpmeg網址:http://ffmpeg.org/

ffmpegapi文檔:http://ffmpeg.org/doxygen/trunk/index.html

因為這是JPG轉MP4,所以不涉及音頻部分,可參考例子解碼:http://ffmpeg.org/doxygen/trunk/decode_video_8c-example.html 編碼:http://ffmpeg.org/doxygen/trunk/encode_video_8c-example.html

一、讀取到的JPG圖像內容需要解碼:

1、打開一個解碼器需要的內容

AVCodec* pDecodec;
AVCodecContext* pDecodecCtx;
AVFrame* pDeFrame;
AVPacket pDePacket;
//讀取jpg用的解碼器mjpeg
pDecodec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
//獲取解碼器上下文
pDecodecCtx = avcodec_alloc_context3(pDecodec);
pDecodecCtx->width = 512;
pDecodecCtx->height = 512;
pDecodecCtx->pix_fmt = AV_PIX_FMT_RGB24;
//打開解碼器
avcodec_open2(pDecodecCtx,pDecodec,NULL);

2、解碼操作

//用一個avstream來接收解碼的數據幀
pDeFrame = av_frame_alloc();
//初始化一個ffmpeg的數據包
av_init_packet(&pDePacket);
unsigned char *jpgdata = new unsigned char[2048*2048];
FILE *file;
file = fopen([需要打開的文件全路徑], "rw");
int readlen = fread(jpgdata, 1, 2048*2048, file);
//調用解碼器解碼
avcodec_decode_video2(pDecodecCtx,pDeFrame,&deCFflag,&pDePacket);

二、創建打開編碼器

AVCodec* pEncodec;
AVCodecContext* pEncodecCtx;
AVFrame* pEnFrame;
AVPacket pEnPacket;

pEncodecCtx = pVideoStream->codec;
pEncodecCtx->codec_id = pOutPutFormatCtx->oformat->video_codec;
pEncodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pEncodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pEncodecCtx->width = 720;
pEncodecCtx->height = 576;
//pEncodecCtx->bit_rate = 400000; 碼流 適用於網絡傳輸
pEncodecCtx->gop_size = 1;
pEncodecCtx->time_base.num = 1;
pEncodecCtx->time_base.den = 25;
pEncodecCtx->qmin = 10;
pEncodecCtx->qmax = 51;
pEncodecCtx->max_b_frames=3;
//質量 文件
pEncodecCtx->bit_rate = 0;
av_opt_set_int(pEncodecCtx->priv_data,"crf",0,0);
//在文件頭寫入文件信息(默認在每個包寫入文件信息,微軟默認播放器可能播放不了)
pEncodecCtx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
//找一個視頻編碼器
pEncodec = avcodec_find_encoder(pEncodecCtx->codec_id);
//打開編碼器
avcodec_open2(pEncodecCtx,pEncodec,NULL); int picture_size =0;
uint8_t* picture_buf;
//初始換編碼用avframe pEnFrame
= av_frame_alloc();
//編碼的圖像大小 picture_size
= avpicture_get_size(pEncodecCtx->pix_fmt,pEncodecCtx->width,pEncodecCtx->height);
//編碼圖像buf picture_buf
= (uint8_t *)av_malloc(picture_size);
//關聯相關屬性 avpicture_fill((AVPicture
*)pEnFrame,picture_buf, pEncodecCtx->pix_fmt,pEncodecCtx->width,pEncodecCtx->height); pEnFrame->width = pEncodecCtx->width; pEnFrame->height = pEncodecCtx->height; pEnFrame->format = pEncodecCtx->pix_fmt;
//初始話編碼的包 av_init_packet(
&pEnPacket);

 

三、輸出文件的信息

AVFormatContext* pOutPutFormatCtx;
AVStream* pVideoStream;

avformat_alloc_output_context2(&pOutPutFormatCtx, NULL, NULL, [輸出的文件全路徑].c_str());
pVideoStream = avformat_new_stream(pOutPutFormatCtx, NULL);
avio_open(&pOutPutFormatCtx->pb,[輸出的文件全路徑],AVIO_FLAG_READ_WRITE); 
av_dump_format(pOutPutFormatCtx,
0,[輸出的文件全路徑],1);
//將編碼器的信息與輸出的信息屬性關聯起來
avcodec_parameters_from_context(pVideoStream->codecpar,pEncodecCtx); av_codec_get_tag2(pOutPutFormatCtx->oformat->codec_tag, pEncodecCtx->codec_id, &pVideoStream->codecpar->codec_tag);
//寫輸出的文件的頭 avformat_write_header(pOutPutFormatCtx,NULL);

四、轉碼,將用解碼器打開的jpg文件轉碼成需要編碼的Frame格式

//FFmpeg的一個轉換類
SwsContext* pImagectx;

pImagectx = sws_getContext(pDecodecCtx->width, pDecodecCtx->height, pDecodecCtx->pix_fmt,pEncodecCtx->width,pEncodecCtx->height, pEncodecCtx->pix_fmt,SWS_BICUBIC, NULL,NULL, NULL);

sws_scale(pImagectx,pDeFrame->data,pDeFrame->linesize,0,pDeFrame->height,pEnFrame->data,pEnFrame->linesize);

 五、編碼寫文件

注釋信息為測試讀取文件的邏輯
//snprintf(imagename, 255, "%d.jpg", i);//X.jpg //string imagefilePath = dir + imagename; //printf("---"); //printf(imagefilePath.c_str()); //printf("\n"); //FILE *file; //file = fopen(imagefilePath.c_str(), "rw"); //int readlen = fread(jpgdata, 1, 2048*2048, file); //printf("----read file success %d \n",readlen); //fclose(file); //pDePacket.data = jpgdata; //pDePacket.size = readlen; //int decodecresult = avcodec_decode_video2(pDecodecCtx,pDeFrame,&deCFflag,&pDePacket); //printf("----decodecresult %d \n",decodecresult); //sws_scale(pImagectx,pDeFrame->data,pDeFrame->linesize,0,pDeFrame->height,pEnFrame->data,pEnFrame->linesize); int gotpicture = 0; pEnFrame->pts = i;
//編碼
avcodec_encode_video2(pEncodecCtx,
&pEnPacket,pEnFrame,&gotpicture); //printf("----encodecresult %d \n",gotpicture); pEnPacket.pts = av_rescale_q(pEnPacket.pts, rational, pVideoStream->time_base); pEnPacket.stream_index = pVideoStream->index;
//將編碼得到的包寫入輸出文件 av_write_frame(pOutPutFormatCtx,
&pEnPacket);
//寫文件尾
av_write_trailer(
pOutPutFormatCtx);

六、釋放資源

av_free_packet(&pDePacket);
    if(pDeFrame != NULL)
    {
        av_free(pDeFrame);
    }
    if(pDecodecCtx != NULL)
    {
         avcodec_close(pDecodecCtx);
    }
av_free_packet(&pEnPacket);
    if(pEnFrame != NULL)
    {
        av_free(pEnFrame);
    }
    if(pEncodecCtx != NULL)
    {
         avcodec_close(pEncodecCtx);
    }

if(pOutPutFormatCtx!= NULL)
    {
        avformat_free_context(pOutPutFormatCtx);
    }
    if(pVideoStream != NULL)
    {
        av_free(pVideoStream);
    }
if(pImagectx != NULL)
    {
        sws_freeContext(pImagectx);
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM