一. 解封裝
pts 是顯示的時間 dts是解碼的時間, 這個時間是用來做同步。
- av_register_all(), 注冊所有的格式。包括解封裝格式和加封裝格式。
- avformat_network_init(), 用於初始化網絡。FFmpeg本身也支持解封裝RTSP的數據,如果要解封裝網絡數據格式,則可調用該函數。
- avformat_open_input()。打開一個文件並解析。可解析的內容包括:視頻流、音頻流、視頻流參數、音頻流參數、視頻幀索引。
- avformat_find_stream_info(),查找格式和索引。有些早期格式它的索引並沒有放到頭當中,需要你到后面探測,就會用到此函數。
- av_find_best_stream(), 當視頻被解封裝出來后,需要分開處理音頻和視頻,需要找到對應的音頻流和視頻流
- 解封裝后涉及到的結構體:
AVFormatContext: 封裝的上下文
AVStream : 存放的是音頻流或視頻流的參數信息
AVPacket: 針對於具體的解封裝完后的一個一個的數據包。
av_read_frame() 用於讀取一個AVPacket,AVPacket里面包含了這個包的pts,dts,還有這個包的stream index(它是音頻還是視頻),是否是關鍵幀,AVPacket把h264數據的間隔符去掉了。
二.avformat_open_input()函數詳解及mp4文件打開示例
2.1 avformat_open_input函數詳解
該函數用於打開一個輸入的封裝器。在調用該函數之前,須確保av_register_all()和avformat_network_init()已調用。
參數說明:
AVFormatContext **ps, 格式化的上下文。要注意,如果傳入的是一個AVFormatContext*的指針,則該空間須自己手動清理,若傳入的指針為空,則FFmpeg會內部自己創建。
const char *url, 傳入的地址。支持http,RTSP,以及普通的本地文件。地址最終會存入到AVFormatContext結構體當中。
AVInputFormat *fmt, 指定輸入的封裝格式。一般傳NULL,由FFmpeg自行探測。
AVDictionary **options, 其它參數設置。它是一個字典,用於參數傳遞,不傳則寫NULL。參見:libavformat/options_table.h,其中包含了它支持的參數設置。
2.2 mp4文件打開示例
extern "C" JNIEXPORT jstring JNICALL Java_com_yuneec_yongdaimi_ff_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) { std::string hello = "Hello from C++"; hello += avcodec_configuration(); // 初始化解封裝 av_register_all(); // 初始化網絡 avformat_network_init(); // 打開文件 AVFormatContext *ic = NULL; char path[] = "sdcard/1080.mp4"; int ret = avformat_open_input(&ic, path, 0, 0); if (ret == 0) { LOGI("avformat_open_input() called success."); } else { LOGE("avformat_open_input() called failed: %s", av_err2str(ret)); } return env->NewStringUTF(hello.c_str()); }
PS:
1.這里用到了avformat_open_input()函數,需要包含其對應的頭文件: #include <libavformat/avformat.h> ;
2.代碼中還用到了 av_err2str() 這個函數,因此CMakeLists.txt中還需要包含它所對應的 libavutil.so 庫,相關的CMakeLists.txt如下:
# avcodec add_library(avcodec SHARED IMPORTED) set_target_properties(avcodec PROPERTIES IMPORTED_LOCATION ${FF}/libavcodec.so) # avformat add_library(avformat SHARED IMPORTED) set_target_properties(avformat PROPERTIES IMPORTED_LOCATION ${FF}/libavformat.so) # avutil add_library(avutil SHARED IMPORTED) set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${FF}/libavutil.so)
另外,不要忘記添加鏈接:
target_link_libraries( # Specifies the target library. native-lib avcodec avformat avutil # Links the target library to the log library # included in the NDK. ${log-lib} )