2012年10月22日 星期一

FFmpeg tutorial practice - tutorial01

FFmpeg 是很有名的 Open source software,它提供了很強大的 Libraries 可以讓你使用,如果你對內部的程式有興趣的話,還可以下載它的原始碼來仔細看看。FFmpeg 網站的文件其實還算不少,但是要能讓你有個入門的說明,真的要花時間好好研究。我在其中找到了較入門且詳細的說明文件,但是它一開始就表明了文件已經過時了,一些原本在 Sample code 裡的程式碼所用的 API 可能都已經不再使用,所以要參考的人注意。也因為這樣,自己就花了一些時間,試著重新建構 Sample code,讓它可以正常編譯且運作。 

原始的說明網站在這裡,有興趣的同好也可以去看看。它提供了8個 tutorial examples,這裡是第一個,也就是 tutorial01。如果一開始直接拿過來編譯,會出現警告和錯誤,這裡就是把這些問題解決的過程。



如何正確的呼叫 Libraries,這裡就不再說明,只提醒一件事,在編譯時要注意呼叫 Libraries 的順序,以免發生很多 undefined 的錯誤訊息。以下是在編譯時呼叫的順序

LIBS       = -lavdevice -lavfilter -lavformat -lavcodec -lz -lpthread
LIBS      += -ldl -lrt -lswresample -lswscale -lavutil -lm

呼叫Libraries沒有問題之後,再來看看怎麼修正其他錯誤。我在處理過程是先註解掉,除了 main function 以外的程式碼,包含 main function 裡的程式,讓事情先簡單化,再一個一個加回去。在加回去的過程中,有幾個 function 是已經 deprecated , 所以要找到對映的 function 來處理。有以下的 function 需要處理:

// Open video file
if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
    return -1; // Couldn't open file
改成
// Open video file
if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
    exit(1);


// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
    return -1; // Couldn't find stream information
改成
// Retrieve stream information
if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
    exit(1);


// Dump information about file onto standard error
dump_format(pFormatCtx, 0, argv[1], 0);
改成
// Dump information about file onto standard error
av_dump_format(pFormatCtx, 0, argv[1], 0);


if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO) {
    videoStream=i;
    break;
}
改成
if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
    videoStream=i;
    break;
}


// Open codec
if(avcodec_open(pCodecCtx, pCodec)<0)
    return -1; // Could not open codec
改成
// Open codec
if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    exit(1);


// Decode video frame
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished, packet.data, packet.size);
改成
// Decode video frame
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);


// Convert the image from its native format to RGB
img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
改成
// Convert the image from its native format to RGB
pSWSContext = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, 640, 480, PIX_FMT_RGB24, SWS_FAST_BILINEAR, 0, 0, 0);
sws_scale(pSWSContext, (const uint8_t * const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

其中,img_convert 已經不再使用,必須用 sws_getContext 和 sws_scale 取代,而大部份參數都是參考原本的設定。


沒有留言:

張貼留言