Matroska 多媒体容器(Multimedia Container)是一种开放标准的自由的容器和文件格式,是一种多媒体封装格式,能够在一个文件中容纳无限数量的视频、音频、图片或字幕轨道。所以其不是一种压缩格式,而是 Matroska 定义的一种多媒体容器文件。其目标是作为一种统一格式保存常见的电影、电视节目等多媒体内容。在概念上 Matroska 和其他容器,比如 AVI、MP4 或 ASF(Advanced Streaming Format,即高级流格式)比较类似,但其在技术规程上完全开放,在实现上包含很多开源软件。可将多种不同编码的视频及 16 条以上不同格式的音频和不同语言的字幕流封装到一个Matroska 媒体文件当中。最大的特点就是能容纳多种不同类型编码的视频、音频及字幕流。
mkv 不同于 DivX、XviD 等视频编码格式,也不同于 MP3、Ogg 等音频编码格式。mkv 是为这些音、视频提供外壳的“组合”和“封装”格式。换句话说就是一种容器格式,常见的 DAT(是 VCD 的一种编码格式)AVl、VOB、MPEG、RM 格式其实也都属于这种类型。但它们要么结构陈旧,要么不够开放,这才促成了 MKV 这类新型多媒体封装格式的诞生。
Matroska 开源多媒体容器标准。MKV 属于其中的一部分。Matroska 常见的有 .MKV 视频格式、MKA 音频格式、.MKS 字幕格式、.MK3D files (stereoscopic/3D video)。MKV 这种多媒体封装是建立在 EBML 语言的基础上,EBML 是可扩展的二进制语言,优势在于其可变长度的整数存储,节省空间。
libmatroska —— 用来解析 Matroska 文件(.mkv和.mka)的 C++ 库
libebml —— 用来解析 EBML 文件的 C++ 库
libmatroska 库除了解析 Matroska 文件,其实还能创建 Matroska 文件,编译 libmatroska 依赖 libebml 库。
一、移植 libebml
- 将源码(github.com/Matroska-Or…)复制到 Android Studio main/cpp 路径下
- 修改 CMakeLists.txt 调用 Cmake 编译 libebml
cmake_minimum_required(VERSION 3.4.1)
project(ebml VERSION 1.3.10)
set(libebml_SOURCES
src/main/cpp/Debug.cpp
src/main/cpp/EbmlBinary.cpp
src/main/cpp/EbmlContexts.cpp
src/main/cpp/EbmlCrc32.cpp
src/main/cpp/EbmlDate.cpp
src/main/cpp/EbmlDummy.cpp
src/main/cpp/EbmlElement.cpp
src/main/cpp/EbmlFloat.cpp
src/main/cpp/EbmlHead.cpp
src/main/cpp/EbmlMaster.cpp
src/main/cpp/EbmlSInteger.cpp
src/main/cpp/EbmlStream.cpp
src/main/cpp/EbmlString.cpp
src/main/cpp/EbmlSubHead.cpp
src/main/cpp/EbmlUInteger.cpp
src/main/cpp/EbmlUnicodeString.cpp
src/main/cpp/EbmlVersion.cpp
src/main/cpp/EbmlVoid.cpp
src/main/cpp/IOCallback.cpp
src/main/cpp/MemIOCallback.cpp
src/main/cpp/MemReadIOCallback.cpp
src/main/cpp/SafeReadIOCallback.cpp
src/main/cpp/StdIOCallback.cpp
#[[src/main/cpp/logger.h]])
set(libebml_PUBLIC_HEADERS
src/main/cpp/ebml/Debug.h
src/main/cpp/ebml/EbmlBinary.h
src/main/cpp/ebml/EbmlConfig.h
src/main/cpp/ebml/EbmlContexts.h
src/main/cpp/ebml/EbmlCrc32.h
src/main/cpp/ebml/EbmlDate.h
src/main/cpp/ebml/EbmlDummy.h
src/main/cpp/ebml/EbmlElement.h
src/main/cpp/ebml/EbmlEndian.h
src/main/cpp/ebml/EbmlFloat.h
src/main/cpp/ebml/EbmlHead.h
src/main/cpp/ebml/EbmlId.h
src/main/cpp/ebml/EbmlMaster.h
src/main/cpp/ebml/EbmlSInteger.h
src/main/cpp/ebml/EbmlStream.h
src/main/cpp/ebml/EbmlString.h
src/main/cpp/ebml/EbmlSubHead.h
src/main/cpp/ebml/EbmlTypes.h
src/main/cpp/ebml/EbmlUInteger.h
src/main/cpp/ebml/EbmlUnicodeString.h
src/main/cpp/ebml/EbmlVersion.h
src/main/cpp/ebml/EbmlVoid.h
src/main/cpp/ebml/IOCallback.h
src/main/cpp/ebml/MemIOCallback.h
src/main/cpp/ebml/MemReadIOCallback.h
src/main/cpp/ebml/SafeReadIOCallback.h
src/main/cpp/ebml/StdIOCallback.h)
set(libebml_C_PUBLIC_HEADERS src/main/cpp/ebml/c/libebml_t.h)
add_library(
ebml
SHARED
${libebml_PUBLIC_HEADERS}
${libebml_C_PUBLIC_HEADERS}
${libebml_SOURCES})
find_library(
log-lib
log)
set_target_properties(ebml PROPERTIES
VERSION 4.0.0
SOVERSION 4)
target_include_directories(ebml
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
include(GenerateExportHeader)
generate_export_header(ebml EXPORT_MACRO_NAME EBML_DLL_API EXPORT_FILE_NAME ebml_export.h)
target_sources(ebml
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/ebml_export.h)
target_link_libraries(
ebml
${log-lib}
jnigraphics)
- 修改 build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "xxx.xxx"
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions -std=c++11"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path file('CMakeLists.txt')
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
编译成功以后 /build/intermediates/cmake/ 路径下可看到正确编译的 libebml 动态库。
二、移植 libmatroska
- 在 Android Studio 新建一个 Module;
- 将源码(github.com/Matroska-Or…)复制到 Android Studio main/cpp 路径下
- 复制 libebml 头文件和编译出的 libebml.so 到此 Module libs 路径下
- 复制 ebml_export.h (.cxx/cmake/debug/armeabi-v7a/ebml_export.h)到 libs/include/ebml/ 路径下,ebml_export.h 是在编译 libebml 时自动生成的,在 Cmake 脚本中配置过
.cxx/cmake/debug/armeabi-v7a/ebml_export.h 路径显示在 Android Studio 中:
libs/include/ebml/ebml_export.h 路径显示在 Android Studio 中:
5. 修改 CMakeLists.txt 调用 Cmake 编译 libmatroska
cmake_minimum_required(VERSION 3.4.1)
project(matroska VERSION 1.5.2)
set(distribution_DIR ../../../../libs)
add_library( ebml
SHARED
IMPORTED)
set_target_properties( ebml
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/${ANDROID_ABI}/libebml.so)
set(libmatroska_SOURCES
src/main/cpp/FileKax.cpp
src/main/cpp/KaxAttached.cpp
src/main/cpp/KaxAttachments.cpp
src/main/cpp/KaxBlock.cpp
src/main/cpp/KaxBlockData.cpp
src/main/cpp/KaxCluster.cpp
src/main/cpp/KaxContexts.cpp
src/main/cpp/KaxCues.cpp
src/main/cpp/KaxCuesData.cpp
src/main/cpp/KaxInfoData.cpp
src/main/cpp/KaxSeekHead.cpp
src/main/cpp/KaxSegment.cpp
src/main/cpp/KaxSemantic.cpp
src/main/cpp/KaxTracks.cpp
src/main/cpp/KaxVersion.cpp
#[[src/main/cpp/logger.h]])
set(libmatroska_PUBLIC_HEADERS
src/main/cpp/matroska/FileKax.h
src/main/cpp/matroska/KaxAttached.h
src/main/cpp/matroska/KaxAttachments.h
src/main/cpp/matroska/KaxBlockData.h
src/main/cpp/matroska/KaxBlock.h
src/main/cpp/matroska/KaxChapters.h
src/main/cpp/matroska/KaxClusterData.h
src/main/cpp/matroska/KaxCluster.h
src/main/cpp/matroska/KaxConfig.h
src/main/cpp/matroska/KaxContentEncoding.h
src/main/cpp/matroska/KaxContexts.h
src/main/cpp/matroska/KaxCuesData.h
src/main/cpp/matroska/KaxCues.h
src/main/cpp/matroska/KaxDefines.h
src/main/cpp/matroska/KaxInfoData.h
src/main/cpp/matroska/KaxInfo.h
src/main/cpp/matroska/KaxSeekHead.h
src/main/cpp/matroska/KaxSegment.h
src/main/cpp/matroska/KaxSemantic.h
src/main/cpp/matroska/KaxTag.h
src/main/cpp/matroska/KaxTags.h
src/main/cpp/matroska/KaxTrackAudio.h
src/main/cpp/matroska/KaxTrackEntryData.h
src/main/cpp/matroska/KaxTracks.h
src/main/cpp/matroska/KaxTrackVideo.h
src/main/cpp/matroska/KaxTypes.h
src/main/cpp/matroska/KaxVersion.h)
set (libmatroska_C_PUBLIC_HEADERS
src/main/cpp/matroska/c/libmatroska.h
src/main/cpp/matroska/c/libmatroska_t.h)
add_library(
matroska
SHARED
${libmatroska_PUBLIC_HEADERS}
${libmatroska_C_PUBLIC_HEADERS}
${libmatroska_SOURCES})
include_directories(libs/include)
find_library(
log-lib
log)
set_target_properties(matroska PROPERTIES
VERSION 6.0.0
SOVERSION 6)
target_include_directories(matroska
PRIVATE
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
include(GenerateExportHeader)
generate_export_header(matroska EXPORT_MACRO_NAME MATROSKA_DLL_API EXPORT_FILE_NAME matroska_export.h)
target_sources(matroska
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/matroska_export.h)
target_link_libraries(
matroska
${log-lib}
jnigraphics
ebml)
- 修改 build.gradle
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
minSdkVersion 23
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
externalNativeBuild {
cmake {
cppFlags "-frtti -fexceptions -std=c++11"
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path file('CMakeLists.txt')
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
- 编译的时候会发现头文件报错,把每个头文件中的内容 include matroska 路径都删掉
编译成功以后 /build/intermediates/cmake/ 路径下可看到正确编译的 libmatroska 动态库。