您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
5. avformat_find_stream_info探测获取封装上下文的格式信息~1
发布时间:2021-05-30 18:28:47编辑:雪饮阅读()
對於不同格式的視頻文件,要獲取其持續時間,也就是時長是需要處理不同的兼容性的。
比如今天這裏要處理的就是mp4和flv。
這裏的視頻原文件flv是通過之前我們用的那個1080.mp4經過格式工廠轉碼輸出的flv的。
對於mp4來説只需要avformat_open_input成功,就可以用AVFormatContext類型左值去調用duration以獲得視頻時常。
但是對於flv來説這樣的操作獲取的時常則是不可靠的。
flv格式在調用duration之前還必須要滿足avformat_find_stream_info調用的成功。
那麽具體的實現如:cpp/native-lib.cpp:
#include <jni.h>
#include <string>
#include <android/log.h>
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndk_1and_141_MainActivity_stringFromJNI(JNIEnv* env,jobject) {
std::string hello = "Hello from C++";
hello+=avcodec_configuration();
//初始化解封裝
av_register_all();
//初始化網絡
avformat_network_init();
AVFormatContext *ic=NULL;
//char path[]="/sdcard/1080.mp4";
char path[]="/sdcard/1080.flv";
int re=avformat_open_input(&ic,path,0,0);
if(re!=0){
LOGW("avformat_open_input failed!:%s",av_err2str(re));
return env->NewStringUTF(hello.c_str());
}
/*
這裏需要漲點教訓,原來這裏是LOGW("avformat_open_input %s success!");
也就是多帶了一個%s,很明顯這裏語法在c中是有問題的,可是編譯過程時候沒有報錯。
日志貓中報錯信息讓我一度懷疑自己的arm64位動態鏈接庫編譯錯了呢。。。
*/
LOGW("avformat_open_input success!");
/*
duration方法:
mp4格式可以直接獲取到時長
返回類型是int64_t:
int64_t 是标准C ++类型,用于完全64位的有符号整数。 int64 不是标准类型。
第一个C ++标准没有固定宽度类型。在将 int64_t 添加到标准C ++之前,不同的编译器都实现了64位类型,但它们使用了自己的名称(例如 long long < / code>, __ int64 等。)
那麽因爲long long < / code>,所以這裏int64_t的輸出就是l ld了
*/
//對於flv來説,要先探測獲取下流信息,若不先探測,則獲取的場地可能就是如:-9223372036854775808一樣的負數
re=avformat_find_stream_info(ic,0);
if(re!=0){
LOGW("avformat_find_stream_info failed!");
}
//這裏格式化int64_t的時候千萬記住不是%lld而是%l ld
LOGW("duration=%l ld nb_streams=%d",ic->duration,ic->nb_streams);
avformat_close_input(&ic);
return env->NewStringUTF(hello.c_str());
}
#include <string>
#include <android/log.h>
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,"testff",__VA_ARGS__)
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ndk_1and_141_MainActivity_stringFromJNI(JNIEnv* env,jobject) {
std::string hello = "Hello from C++";
hello+=avcodec_configuration();
//初始化解封裝
av_register_all();
//初始化網絡
avformat_network_init();
AVFormatContext *ic=NULL;
//char path[]="/sdcard/1080.mp4";
char path[]="/sdcard/1080.flv";
int re=avformat_open_input(&ic,path,0,0);
if(re!=0){
LOGW("avformat_open_input failed!:%s",av_err2str(re));
return env->NewStringUTF(hello.c_str());
}
/*
這裏需要漲點教訓,原來這裏是LOGW("avformat_open_input %s success!");
也就是多帶了一個%s,很明顯這裏語法在c中是有問題的,可是編譯過程時候沒有報錯。
日志貓中報錯信息讓我一度懷疑自己的arm64位動態鏈接庫編譯錯了呢。。。
*/
LOGW("avformat_open_input success!");
/*
duration方法:
mp4格式可以直接獲取到時長
返回類型是int64_t:
int64_t 是标准C ++类型,用于完全64位的有符号整数。 int64 不是标准类型。
第一个C ++标准没有固定宽度类型。在将 int64_t 添加到标准C ++之前,不同的编译器都实现了64位类型,但它们使用了自己的名称(例如 long long < / code>, __ int64 等。)
那麽因爲long long < / code>,所以這裏int64_t的輸出就是l ld了
*/
//對於flv來説,要先探測獲取下流信息,若不先探測,則獲取的場地可能就是如:-9223372036854775808一樣的負數
re=avformat_find_stream_info(ic,0);
if(re!=0){
LOGW("avformat_find_stream_info failed!");
}
//這裏格式化int64_t的時候千萬記住不是%lld而是%l ld
LOGW("duration=%l ld nb_streams=%d",ic->duration,ic->nb_streams);
avformat_close_input(&ic);
return env->NewStringUTF(hello.c_str());
}
對於上面LOGW("avformat_open_input success!")之前我把括號裏面多了一個%s導致日志貓中出現錯誤如:A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8000
這種不清不楚的問題,真的是很頭大,所以還是要更加細心寫,特別是對於c和安卓java混合編程時候,真的是一個頭兩個大。
那麽最後讓我們編譯執行看看日志貓中對於flv視頻時常的獲取:
2021-05-30 18:25:21.212 3577-3577/com.example.ndk_and_41 W/testff: avformat_open_input success!
2021-05-30 18:25:21.215 3577-3577/com.example.ndk_and_41 W/testff: duration= 257750000 nb_streams=2
是的,這樣就沒有什麽問題了。
需要補充説明的就是:
nb_streams:视音频流的个数
关键字词:avformat_find_stream_info,int64_t,Fatal signal 11
相关文章
-
无相关信息