apiexample.c例子教我們如何去利用ffmpeg庫中的api函數來自己編寫編解碼程序。
(1)首先,main函數中一開始會去調用avcodec_init()函數,該函數的作用是初始化libavcodec,而我們在使用avcodec庫時,該函數必須被調用。
(2)avcodec_register_all()函數,注冊所有的編解碼器(codecs),解析器(parsers)以及碼流過濾器(bitstream filters)。當然我們也可以使用個別的注冊函數來注冊我們所要支持的格式。
(3)video_encode_example()函數用于 視頻編碼 ,由圖可知,所有的編碼工作都在該函數內完成。
(4)avcodec_find_encoder()函數用于查找一個與codec ID相匹配的已注冊的編碼器。
(5)avcodec_alloc_context()函數用于分配一個AVCodecContext并設置默認值,如果失敗返回NULL,并可用av_free()進行釋放。
(6)avcodec_alloc_frame()函數用于分配一個AVFrame并設置默認值,如果失敗返回NULL,并可用av_free()進行釋放。
(7)設置參數:
設置采樣參數,即比特率。
c->bit_rate = 400000;
設置分辨率,必須是2的倍數。
c->width = 352;
c->height = 288;
設置幀率。
c->time_base = (AVRational){1,25}; 該幀率為25,其實timebase = 1/framerate,花括號內分別為分子和分母。
設置GOP大小。
c->gop_size = 10; 該值表示每10幀會插入一個I幀(intra frame)。
設置B幀最大數。
c->max_b_frames = 1; 該值表示在兩個非B幀之間,所允許插入的B幀的最大幀數。
設置像素格式。
c->pix_fmt = PIX_FMT_YUV420P; 該值將像素格式設置為YUV420P。
(8)avcodec_open()函數用給定的AVCodec來初始化AVCodecContext。
(9)接著是打開文件,f = fopen( filename, “wb” );
(10)分配圖像和輸出緩存。
申請100KB左右的內存作為輸出緩存。
outbuf_size = 100000;
outbuf = malloc( outbuf_size );
根據幀的大小來確定YUV420所占內存大小,一個像素,RGB格式占用3個字節,而YUV420格式只占用兩個字節。YUV420格式是指,每個像素都保留一個Y(亮度)分量,而在水平方向上,不是每行都取U和V分量,而是一行只取U分量,則其接著一行就只取V分量,以此重復,所以420不是指沒有V,而是指一行采樣只取U,另一行采樣只取V。在取U和V時,每兩個Y之間取一個U或V。但從4x4矩陣列來看,每4個矩陣點Y區域中,只有一個U和V,所以它們的比值是4:1。所以對于一個像素,RGB需要8 * 3 = 24位,即占3個字節;而YUV420P,8 + 8/4 + 8/4 = 12位,即占2個字節,其中8指Y分量,8/4指U和V分量。
size = c->width * c->height;
picture_buf = malloc( (size * 3) / 2 );
picture->data[0] = picture_buf;
picture->data[1] = picture->data[0] + size;
picture->data[2] = picture->data[1] + size / 4;
picture->linesize[0] = c->width;
picture->linesize[1] = c->width / 2;
picture->linesize[2] = c->width / 2;
其中,data[0]存放Y,data[1]存放U,data[2]存放V【FixMe】。linesize[0]表示Y分量的寬度,linesize[1]表示U分量的寬度,linesize[2]表示V分量的寬度。
(11)編碼一秒鐘的視頻,幀率為25,所以需要循環25次,每次編碼一幀。
(11.1)準備一幅偽圖像,即自己自定義往里面塞數據。
for(y=0;y<c->height;y++){
for(x=0;x<c->width;x++){
picture->data[0][y*picture->linesize[0]+x]=x+y+i*3;
}
}
for(y=0;y<c->height/2;y++){
for(x=0;x<c->width/2;x++){
picture->data[1][y*picture->linesize[1]+x]=128+y+i*2;
picture->data[2][y*picture->linesize[2]+x]=64+x+i*5;
}
}
(11.2)avcodec_encode_video()從picture中編碼一幀視頻數據,并存入到outbuf中,而期間所使用的編碼器為c。
(11.3)將編碼完的數據寫入到文件里。
(12)對延時的幀數據進行編碼。因為像MPEG4中,I幀、P幀和B幀之間存在一定的延時【FixMe】。同樣是avcodec_encode_video(),然后寫入文件。
(13)添加結束代碼,使其成為一個真正的mpeg文件。
outbuf[0] = 0x00;
outbuf[1] = 0x00;
outbuf[2] = 0x01;
outbuf[3] = 0xb7;
fwrite( outbuf, 1, 4, f );
這個結束代碼表示什么???
(14)釋放資源。
fclose(f);
free(picture_buf);
free(outbuf);
avcodec_close(c);
av_free(c);
av_free(picture);
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
