Android 音視頻深入 九 FFmpeg解碼視頻產生yuv檔案(附源碼下載)

來源:互聯網
上載者:User

標籤:break   輸入   檔案的   while   相關   www   find   buffer   針對   

項目地址,求star

https://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg(MP4%E8%BD%ACyuv%EF%BC%89

這一次是將MP4解碼出yuv檔案出來,先介紹一波yuv檔案

YUV是指亮度參量和色度參量分開表示的像素格式,而這樣分開的好處就是不但可以避免相互幹擾,還可以降低色度的採樣率而不會對映像品質影響太大。YUV是一個比較籠統地說法,針對它的具體相片順序,可以分為很多種具體的格式。

直接上主菜,如何將MP4解碼出yuv檔案

首先在java使用NDK,調用解碼函數,輸入MP4檔案的路徑和輸出yuv檔案的路徑
decode(inputurl,outputurl);

接下來就是正式的解說FFmpeg相關函數的作用了

先來一張圖片,理清代碼運行順序

接下來看注釋,。。。。要是每一個函數詳細的講,我做不到,也寫不完,重在熟悉流程

//1.註冊所有組件
av_register_all();
//初始網路流
avformat_network_init();
//封裝格式上下文,統領全域的結構體,儲存了視頻檔案封裝格式的相關資訊
pFormatCtx = avformat_alloc_context();
//2.開啟輸入視頻檔案
if(avformat_open_input(&pFormatCtx,input_str,NULL,NULL)!=0){
LOGE("Couldn‘t open input stream.\n");
return -1;
}
//3.擷取視頻檔案資訊
if(avformat_find_stream_info(pFormatCtx,NULL)<0){
LOGE("Couldn‘t find stream information.\n");
return -1;
}
//擷取視頻流的索引位置
//遍曆所有類型的流(音頻流、視頻流、字幕流),找到視頻流
videoindex=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
videoindex=i;
break;
}
if(videoindex==-1){
LOGE("Couldn‘t find a video stream.\n");
return -1;
}
//只有知道視頻的編碼方式,才能夠根據編碼方式去找到解碼器
//擷取視頻流中的編解碼上下文
pCodecCtx=pFormatCtx->streams[videoindex]->codec;
//4.根據編解碼上下文中的編碼id尋找對應的解碼
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL){
LOGE("Couldn‘t find Codec.\n");
return -1;
}
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0){
LOGE("Couldn‘t open codec.\n");
return -1;
}

pFrame=av_frame_alloc();pFrameYUV=av_frame_alloc();out_buffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,  pCodecCtx->width, pCodecCtx->height,1));av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize,out_buffer,                     AV_PIX_FMT_YUV420P,pCodecCtx->width, pCodecCtx->height,1);//準備讀取//AVPacket用於儲存一幀一幀的壓縮資料(H264)//緩衝區,開闢空間packet=(AVPacket *)av_malloc(sizeof(AVPacket));

//用於轉碼(縮放)的參數,轉之前的寬高,轉之後的寬高,格式等
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

//輸出視頻資訊
sprintf(info, "[Input ]%s\n", input_str);
sprintf(info, "%s[Output ]%s\n",info,output_str);
sprintf(info, "%s[Format ]%s\n",info, pFormatCtx->iformat->name);
sprintf(info, "%s[Codec ]%s\n",info, pCodecCtx->codec->name);
sprintf(info, "%s[Resolution]%dx%d\n",info, pCodecCtx->width,pCodecCtx->height);

fp_yuv=fopen(output_str,"wb+");if(fp_yuv==NULL){    printf("Cannot open output file.\n");    return -1;}frame_cnt=0;time_start = clock();

//6.一幀一幀的讀取壓縮資料
while(av_read_frame(pFormatCtx, packet)>=0){
//只要視頻壓縮資料(根據流的索引位置判斷)
if(packet->stream_index==videoindex){
//7.解碼一幀視頻壓縮資料,得到視頻像素資料
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
if(ret < 0){
LOGE("Decode Error.\n");
return -1;
}
//為0說明解碼完成,非0正在解碼
if(got_picture){
//AVFrame轉為像素格式YUV420,寬高
//2 6輸入、輸出資料
//3 7輸入、輸出畫面一行的資料的大小 AVFrame 轉換是一行一行轉換的
//4 輸入資料第一列要轉碼的位置 從0開始
//5 輸入畫面的高度
sws_scale(img_convert_ctx, (const uint8_t const)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
pFrameYUV->data, pFrameYUV->linesize);
//輸出到YUV檔案
//AVFrame像素幀寫入檔案
//data解碼後的映像像素資料(音頻採樣資料)
//Y 亮度 UV 色度(壓縮了) 人對亮度更加敏感
//U V 個數是Y的1/4
y_size=pCodecCtx->width*pCodecCtx->height;
fwrite(pFrameYUV->data[0],1,y_size,fp_yuv); //Y
fwrite(pFrameYUV->data[1],1,y_size/4,fp_yuv); //U
fwrite(pFrameYUV->data[2],1,y_size/4,fp_yuv); //V
//Output info
char pictype_str[10]={0};
switch(pFrame->pict_type){
case AV_PICTURE_TYPE_I:sprintf(pictype_str,"I");break;
case AV_PICTURE_TYPE_P:sprintf(pictype_str,"P");break;
case AV_PICTURE_TYPE_B:sprintf(pictype_str,"B");break;
default:sprintf(pictype_str,"Other");break;
}
LOGI("Frame Index: %5d. Type:%s",frame_cnt,pictype_str);
//釋放資源
frame_cnt++;
}
}
av_free_packet(packet);
}

這隻是說如何解碼視頻,還有音頻沒有解碼,但是過程相似,甚至更簡單

參考文章:
https://www.cnblogs.com/CoderTian/p/6791638.html

Android 音視頻深入 九 FFmpeg解碼視頻產生yuv檔案(附源碼下載)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.