1# 媒体数据解析 2 3<!--Kit: AVCodec Kit--> 4<!--Subsystem: Multimedia--> 5<!--Owner: @zhanghongran--> 6<!--Designer: @dpy2650---> 7<!--Tester: @cyakee--> 8<!--Adviser: @zengyawen--> 9 10开发者可以调用本模块的Native API接口,完成媒体数据的解封装相关操作,即从比特流数据中取出音频、视频、字幕等媒体sample,获得DRM相关信息。 11 12当前支持的数据输入类型有:远程连接(http协议)和文件描述符(fd)。 13 14当前支持的解封装格式请参考[AVCodec支持的格式](avcodec-support-formats.md#媒体数据解析)。 15 16**适用场景**: 17 18- 播放 19 20 播放媒体文件时,需要先对媒体流进行解封装,然后使用解封装获取的sample进行解码和播放。 21 22- 音视频编辑 23 24 编辑媒体文件时,需要先对媒体流进行解封装,获取到指定sample进行编辑。 25 26- 媒体文件格式转换(转封装) 27 28 媒体文件格式转换时,需要先对媒体流进行解封装,然后按需将媒体流封装至新的格式文件内。 29 30## 开发指导 31 32详细的API说明参考[AVDemuxer](../../reference/apis-avcodec-kit/_a_v_demuxer.md)和[AVSource](../../reference/apis-avcodec-kit/_a_v_source.md) 33 34> **说明** 35> 36> - 调用解封装能力解析网络播放路径,需要[声明权限](../../security/AccessToken/declare-permissions.md):ohos.permission.INTERNET 37> - 调用解封装能力解析本地文件,需要[向用户申请授权](../../security/AccessToken/request-user-authorization.md):ohos.permission.READ_MEDIA 38> - 如果使用ResourceManager.getRawFd打开HAP资源文件描述符,使用方法请参考[ResourceManager API参考](../../reference/apis-localization-kit/js-apis-resource-manager.md#getrawfd9) 39 40### 在 CMake 脚本中链接动态库 41 42``` cmake 43target_link_libraries(sample PUBLIC libnative_media_codecbase.so) 44target_link_libraries(sample PUBLIC libnative_media_avdemuxer.so) 45target_link_libraries(sample PUBLIC libnative_media_avsource.so) 46target_link_libraries(sample PUBLIC libnative_media_core.so) 47``` 48 49> **说明:** 50> 51> 上述'sample'字样仅为示例,此处由开发者根据实际工程目录自定义。 52> 53 54### 开发步骤 55 561. 添加头文件。 57 58 ```c++ 59 #include <multimedia/player_framework/native_avdemuxer.h> 60 #include <multimedia/player_framework/native_avsource.h> 61 #include <multimedia/player_framework/native_avcodec_base.h> 62 #include <multimedia/player_framework/native_avformat.h> 63 #include <multimedia/player_framework/native_avbuffer.h> 64 #include <fcntl.h> 65 #include <sys/stat.h> 66 #include <string> 67 ``` 68 692. 创建资源管理实例。 70 71 开发者HAP中使用open获取fd时,filepath需要转换为[沙箱路径](../../file-management/app-sandbox-directory.md#应用沙箱路径和真实物理路径的对应关系),才能获取沙盒资源。 72 73 ```c++ 74 // 创建文件操作符 fd,打开时对文件实例必须有读权限(filePath 为待解封装文件路径,需预置文件,保证路径指向的文件存在)。 75 std::string filePath = "test.mp4"; 76 int32_t fd = open(filePath.c_str(), O_RDONLY); 77 struct stat fileStatus {}; 78 int64_t fileSize = 0; 79 if (stat(filePath.c_str(), &fileStatus) == 0) { 80 fileSize = static_cast<int64_t>(fileStatus.st_size); 81 } else { 82 printf("get stat failed"); 83 return; 84 } 85 // 为 fd 资源文件创建 source 资源实例, 传入 offset 不为文件起始位置或 size 不为文件大小时,可能会因不能获取完整数据导致 source 创建失败、或后续解封装失败等问题。 86 OH_AVSource *source = OH_AVSource_CreateWithFD(fd, 0, fileSize); 87 if (source == nullptr) { 88 printf("create source failed"); 89 return; 90 } 91 // 为 uri 资源文件创建 source 资源实例(可选)。 92 // OH_AVSource *source = OH_AVSource_CreateWithURI(uri); 93 94 // 为自定义数据源创建 source 资源实例(可选)。使用该方式前,需要先实现AVSourceReadAt接口函数实现。 95 // 当使用OH_AVSource_CreateWithDataSource时需要补充g_filePath。 96 // g_filePath = filePath ; 97 // OH_AVDataSource dataSource = {fileSize, AVSourceReadAt}; 98 // OH_AVSource *source = OH_AVSource_CreateWithDataSource(&dataSource); 99 ``` 100 101 AVSourceReadAt接口函数,需要放在创建资源管理实例前实现: 102 103 ```c++ 104 // 添加头文件。 105 #include <fstream> 106 ``` 107 108 ```c++ 109 static std::string g_filePath; 110 111 enum MediaDataSourceError : int32_t { 112 SOURCE_ERROR_IO = -2, 113 SOURCE_ERROR_EOF = -1 114 }; 115 116 int32_t AVSourceReadAt(OH_AVBuffer *data, int32_t length, int64_t pos) 117 { 118 if (data == nullptr) { 119 printf("AVSourceReadAt : data is nullptr!\n"); 120 return MediaDataSourceError::SOURCE_ERROR_IO; 121 } 122 123 std::ifstream infile(g_filePath, std::ofstream::binary); 124 if (!infile.is_open()) { 125 printf("AVSourceReadAt : open file failed! file:%s\n", g_filePath.c_str()); 126 return MediaDataSourceError::SOURCE_ERROR_IO; // 打开文件失败。 127 } 128 129 infile.seekg(0, std::ios::end); 130 int64_t fileSize = infile.tellg(); 131 if (pos >= fileSize) { 132 printf("AVSourceReadAt : pos over or equals file size!\n"); 133 return MediaDataSourceError::SOURCE_ERROR_EOF; // pos已经是文件末尾位置,无法读取。 134 } 135 136 if (pos + length > fileSize) { 137 length = fileSize - pos; // pos+length长度超过文件大小时,读取从pos到文件末尾的数据。 138 } 139 140 infile.seekg(pos, std::ios::beg); 141 if (length <= 0) { 142 printf("AVSourceReadAt : raed length less than zero!\n"); 143 return MediaDataSourceError::SOURCE_ERROR_IO; 144 } 145 char* buffer = new char[length]; 146 infile.read(buffer, length); 147 infile.close(); 148 149 memcpy(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)), 150 buffer, length); 151 delete[] buffer; 152 153 return length; 154 } 155 ``` 1563. 创建解封装器实例。 157 ```c++ 158 // 为资源实例创建对应的解封装器。 159 OH_AVDemuxer *demuxer = OH_AVDemuxer_CreateWithSource(source); 160 if (demuxer == nullptr) { 161 printf("create demuxer failed"); 162 return; 163 } 164 ``` 1654. 注册[DRM信息监听函数](../../reference/apis-avcodec-kit/_a_v_demuxer.md#demuxer_mediakeysysteminfocallback)(可选,若非DRM码流或已获得[DRM信息](../../reference/apis-drm-kit/capi-drm-drm-mediakeysysteminfo.md),可跳过此步)。 166 167 设置DRM信息监听的接口,回调函数支持返回解封装器实例,适用于多个解封装器场景。 168 169 ```c++ 170 // DRM信息监听回调OnDrmInfoChangedWithObj实现。 171 static void OnDrmInfoChangedWithObj(OH_AVDemuxer *demuxer, DRM_MediaKeySystemInfo *drmInfo) 172 { 173 // 解析DRM信息,包括数量、DRM类型及对应pssh。 174 } 175 176 Demuxer_MediaKeySystemInfoCallback callback = &OnDrmInfoChangedWithObj; 177 Drm_ErrCode ret = OH_AVDemuxer_SetDemuxerMediaKeySystemInfoCallback(demuxer, callback); 178 ``` 179 在监听到DRM信息后,也可主动调用获取DRM信息(uuid及对应pssh)接口。 180 181 ```c++ 182 DRM_MediaKeySystemInfo mediaKeySystemInfo; 183 OH_AVDemuxer_GetMediaKeySystemInfo(demuxer, &mediaKeySystemInfo); 184 ``` 185 在获取、解析DRM信息后,需创建对应DRM解决方案的[MediaKeySystem、MediaKeySession](../drm/drm-c-dev-guide.md),获取DRM许可证等。并根据需要设置音频解密配置(详见[音频解码开发指南开发步骤](audio-decoding.md#开发步骤)第4步)、设置视频解密配置(详见[视频解码开发指南开发步骤Surface模式](video-decoding.md#surface模式)第5步或[Buffer模式](video-decoding.md#buffer模式)第4步),实现DRM内容解密。 186 1875. 获取文件信息。 188 189 ```c++ 190 // 获取文件用户自定义属性(可选,若用户无需获取自定义属性,可跳过此步)。 191 // 从文件 source 获取用户自定义属性信息。 192 OH_AVFormat *customMetadataFormat = OH_AVSource_GetCustomMetadataFormat(source); 193 if (customMetadataFormat == nullptr) { 194 // 需释放前置流程资源,参考第10步。 195 printf("get custom metadata format failed"); 196 return; 197 } 198 // 注意事项: 199 // 1. customKey需与封装时写入的key完全一致(含完整命名层级), 200 // 示例key仅为演示,实际应替换为用户自定义的字符串。 201 // 例:封装时写入key为"com.openharmony.custom.meta.abc.efg", 202 // 获取时必须使用完整key,截断使用"com.openharmony.custom.meta.abc"会失败。 203 // 2. value类型需与封装时数据类型匹配,示例为string类型。其余类型需调用对应接口,支持int/float类型;API 20起,支持buffer类型。 204 const char *customKey = "com.openharmony.custom.meta.string"; // 替换为实际封装时使用的完整key。 205 const char *customValue; 206 if (!OH_AVFormat_GetStringValue(customMetadataFormat, customKey, &customValue)) { 207 printf("get custom metadata from custom metadata format failed"); 208 } 209 OH_AVFormat_Destroy(customMetadataFormat); 210 customMetadataFormat = nullptr; 211 212 // 获取文件轨道数(可选,若用户已知轨道信息,可跳过此步)。 213 // 从文件 source 信息获取文件轨道数,用户可通过该接口获取文件级别属性,具体支持信息参考附表 1。 214 OH_AVFormat *sourceFormat = OH_AVSource_GetSourceFormat(source); 215 if (sourceFormat == nullptr) { 216 // 需释放前置流程资源,参考第10步。 217 printf("get source format failed"); 218 return; 219 } 220 int32_t trackCount = 0; 221 if (!OH_AVFormat_GetIntValue(sourceFormat, OH_MD_KEY_TRACK_COUNT, &trackCount)) { 222 printf("get track count from source format failed"); 223 } 224 if (trackCount == 0) { 225 // 文件中无轨道,需根据业务做其他处理。 226 printf("no track"); 227 } 228 OH_AVFormat_Destroy(sourceFormat); 229 sourceFormat = nullptr; 230 ``` 231 2326. 获取轨道index及信息(可选,若用户已知轨道信息,可跳过此步)。 233 234 ```c++ 235 uint32_t audioTrackIndex = 0; 236 uint32_t videoTrackIndex = 0; 237 int32_t w = 0; 238 int32_t h = 0; 239 int64_t bitRate = 0; // 配置比特率,单位为bps。 240 double frameRate = 0.0; 241 const char* mimetype = nullptr; 242 uint8_t *codecConfig = nullptr; 243 size_t bufferSize = 0; 244 int32_t trackType; 245 for (uint32_t index = 0; index < (static_cast<uint32_t>(trackCount)); index++) { 246 // 获取轨道信息,用户可通过该接口获取对应轨道级别属性,具体支持信息参考附表 2。 247 OH_AVFormat *trackFormat = OH_AVSource_GetTrackFormat(source, index); 248 if (trackFormat == nullptr) { 249 printf("get track format failed"); 250 return; 251 } 252 if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_TRACK_TYPE, &trackType)) { 253 printf("get track type from track format failed"); 254 return; 255 } 256 if (trackType == OH_MediaType::MEDIA_TYPE_AUXILIARY) { 257 const char *referenceType; 258 if (!OH_AVFormat_GetStringValue(trackFormat, OH_MD_KEY_TRACK_REFERENCE_TYPE, &referenceType)) { 259 printf("get reference type from auxiliary track failed"); 260 } 261 int32_t* referenceIds; 262 size_t referenceIdsCount; 263 if (!OH_AVFormat_GetIntBuffer(trackFormat, OH_MD_KEY_TRACK_REFERENCE_TYPE, &referenceIds, &referenceIdsCount)) { 264 printf("get reference track ids from auxiliary track failed"); 265 } 266 // 根据辅助轨类型处理轨道参考关系。 267 } 268 static_cast<OH_MediaType>(trackType) == OH_MediaType::MEDIA_TYPE_AUD ? audioTrackIndex = index : videoTrackIndex = index; 269 // 获取视频轨宽高。 270 if (trackType == OH_MediaType::MEDIA_TYPE_VID) { 271 if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_WIDTH, &w)) { 272 printf("get track width from track format failed"); 273 return; 274 } 275 if (!OH_AVFormat_GetIntValue(trackFormat, OH_MD_KEY_HEIGHT, &h)) { 276 printf("get track height from track format failed"); 277 return; 278 } 279 if (!OH_AVFormat_GetLongValue(trackFormat, OH_MD_KEY_BITRATE, &bitRate)) { 280 printf("get track bitRate from track format failed"); 281 return; 282 } 283 if (!OH_AVFormat_GetDoubleValue(trackFormat, OH_MD_KEY_FRAME_RATE, &frameRate)) { 284 printf("get track frameRate from track format failed"); 285 return; 286 } 287 if (!OH_AVFormat_GetStringValue(trackFormat, OH_MD_KEY_CODEC_MIME, &mimetype)) { 288 printf("get track mimetype from track format failed"); 289 return; 290 } 291 if (!OH_AVFormat_GetBuffer(trackFormat, OH_MD_KEY_CODEC_CONFIG, &codecConfig, &bufferSize)) { 292 printf("get track codecConfig from track format failed"); 293 return; 294 } 295 printf(" track width%d, track height:%d, track bitRate:%ld, track frameRate:%f, track mimetype:%s\n", w, h, bitRate, frameRate, mimetype); 296 } 297 OH_AVFormat_Destroy(trackFormat); 298 trackFormat = nullptr; 299 } 300 ``` 301 3027. 添加解封装轨道。 303 304 ```c++ 305 if(OH_AVDemuxer_SelectTrackByID(demuxer, audioTrackIndex) != AV_ERR_OK){ 306 printf("select audio track failed: %d", audioTrackIndex); 307 return; 308 } 309 if(OH_AVDemuxer_SelectTrackByID(demuxer, videoTrackIndex) != AV_ERR_OK){ 310 printf("select video track failed: %d", videoTrackIndex); 311 return; 312 } 313 // 取消选择轨道(可选)。 314 // OH_AVDemuxer_UnselectTrackByID(demuxer, audioTrackIndex); 315 ``` 316 3178. 调整轨道到指定时间点(可选)。 318 319 ```c++ 320 // 调整轨道到指定时间点,后续从该时间点进行解封装。 321 // 注意: 322 // 1. mpegts、mpg 格式文件使用OH_AVDemuxer_SeekToTime功能时,跳转到的位置可能为非关键帧。可在跳转后调用OH_AVDemuxer_ReadSampleBuffer,通过获取到的OH_AVCodecBufferAttr判断当前帧是否为关键帧。若非关键帧影响应用侧显示等功能,可在跳转后循环读取,获取到后续第一帧关键帧后,再进行解码等处理。 323 // 2. ogg格式文件使用OH_AVDemuxer_SeekToTime功能时,会跳转到传入时间millisecond所在时间间隔(秒)的起始处,可能会导致一定数量的帧误差。 324 // 3. demuxer的seek处理只针对解码行为一致的码流进行处理,如果seek后需要解码器重新配置参数,或者需要重新送入参数集的数据才可以正确解码的码流,seek后可能会出现花屏、解码卡死等问题。 325 OH_AVDemuxer_SeekToTime(demuxer, 0, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC); 326 ``` 327 3289. 开始解封装,循环获取sample(以含音频、视频两轨的文件为例)。 329 330 BufferAttr包含的属性: 331 - size:sample尺寸; 332 - offset:数据在AVBuffer中的偏移,一般为0; 333 - pts:文件封装的显示时间戳; 334 - flags:sample属性。 335 336 | flag | 描述 | 337 | -------- | -------- | 338 | AVCODEC_BUFFER_FLAGS_NONE | 默认。 | 339 | AVCODEC_BUFFER_FLAGS_EOS | 结尾sample,数据为空。 | 340 | AVCODEC_BUFFER_FLAGS_SYNC_FRAME | IDR帧或I帧。 | 341 | AVCODEC_BUFFER_FLAGS_INCOMPLETE_FRAME | 非完整的sample,一般由于buffer过小,无法拷贝完整的sample。 | 342 | AVCODEC_BUFFER_FLAGS_CODEC_DATA | 含参数集信息的帧。 | 343 | AVCODEC_BUFFER_FLAGS_DISCARD | 可丢弃的帧。 | 344 345 OH_AVDemuxer_ReadSampleBuffer接口本身可能存在耗时久,取决于文件IO,建议以异步方式进行调用。 346 ```c++ 347 // 为每个线程定义处理函数。 348 void ReadTrackSamples(OH_AVFormatDemuxer *demuxer, uint32_t trackIndex, int buffer_size, 349 std::atomic<bool>& isEnd, std::atomic<bool>& threadFinished) 350 { 351 // 创建缓冲区。 352 OH_AVBuffer *buffer = OH_AVBuffer_Create(buffer_size); 353 if (buffer == nullptr) { 354 printf("Create buffer failed for track %d\n", trackIndex); 355 threadFinished.store(true); 356 return; 357 } 358 OH_AVCodecBufferAttr info; 359 int32_t ret; 360 361 while (!isEnd.load()) { 362 ret = OH_AVDemuxer_ReadSampleBuffer(demuxer, trackIndex, buffer); 363 if (ret == AV_ERR_OK) { 364 OH_AVBuffer_GetBufferAttr(buffer, &info); 365 printf("Track %d sample size: %d\n", trackIndex, info.size); 366 // 检查EOS标志。 367 if (info.flags == OH_AVCodecBufferFlags::AVCODEC_BUFFER_FLAGS_EOS) { 368 isEnd.store(true); 369 } 370 // 处理缓冲区数据(这里可以根据需要实现解码逻辑)。 371 } else { 372 printf("Read sample failed for track %d\n", trackIndex); 373 break; 374 } 375 } 376 // 销毁缓冲区。 377 OH_AVBuffer_Destroy(buffer); 378 buffer = nullptr; 379 threadFinished.store(true); 380 } 381 382 // 根据需求计算合适的缓冲区大小。 383 int audioBufferSize = 4096; // 典型音频缓冲区大小。 384 int videoBufferSize = w * h * 3 >> 1; // 原始视频缓冲区大小。 385 386 // 创建原子变量用于线程通信。 387 std::atomic<bool> audioIsEnd{false}, videoIsEnd{false}; // 表示流是否结束。 388 std::atomic<bool> audioThreadFinished{false}, videoThreadFinished{false}; // 表示线程是否暂停。 389 390 // 创建线程。 391 std::thread audioThread(ReadTrackSamples, demuxer, audioTrackIndex, audioBufferSize, 392 std::ref(audioIsEnd), std::ref(audioThreadFinished)); 393 std::thread videoThread(ReadTrackSamples, demuxer, videoTrackIndex, videoBufferSize, 394 std::ref(videoIsEnd), std::ref(videoThreadFinished)); 395 audioThread.join(); 396 videoThread.join(); 397 ``` 398 39910. 销毁解封装实例。 400 ```c++ 401 // 需要用户调用 OH_AVSource_Destroy 接口成功后,手动将实例置为nullptr,对同一实例重复调用 OH_AVSource_Destroy 会导致程序错误。 402 if (OH_AVSource_Destroy(source) != AV_ERR_OK) { 403 printf("destroy source pointer error"); 404 } 405 source = nullptr; 406 // 需要用户调用 OH_AVDemuxer_Destroy 接口成功后,手动将实例置为nullptr,对同一实例重复调用 OH_AVDemuxer_Destroy 会导致程序错误。 407 if (OH_AVDemuxer_Destroy(demuxer) != AV_ERR_OK) { 408 printf("destroy demuxer pointer error"); 409 } 410 demuxer = nullptr; 411 close(fd); 412 ``` 413 414## 附表 415### 文件级别属性支持范围 416 417> **说明:** 418> 正常解析时才可以获取对应属性数据,如果文件信息错误或缺失,将导致解析异常,无法获取数据。 419> 当前GBK格式字符集数据会转换为UTF8提供,其他类型字符集如果需要转换为UTF8格式使用,需要调用方自行转换,参考[icu4c](../../reference/native-lib/icu4c.md)。 420> 421> 数据类型及详细取值范围参考[媒体数据键值对](../../reference/apis-avcodec-kit/_codec_base.md#媒体数据键值对)。 422 423**表1** 文件级别属性支持范围 424| 名称 | 描述 | 425| -- | -- | 426|OH_MD_KEY_TITLE|文件标题的键| 427|OH_MD_KEY_ARTIST|文件艺术家的键| 428|OH_MD_KEY_ALBUM|文件专辑的键| 429|OH_MD_KEY_ALBUM_ARTIST|文件专辑艺术家的键| 430|OH_MD_KEY_DATE|文件日期的键| 431|OH_MD_KEY_COMMENT|文件注释的键| 432|OH_MD_KEY_GENRE|文件流派的键| 433|OH_MD_KEY_COPYRIGHT|文件版权的键| 434|OH_MD_KEY_LANGUAGE|文件语言的键| 435|OH_MD_KEY_DESCRIPTION|文件描述的键| 436|OH_MD_KEY_LYRICS|文件歌词的键| 437|OH_MD_KEY_TRACK_COUNT|文件轨道数量的键| 438|OH_MD_KEY_DURATION|文件时长的键| 439|OH_MD_KEY_START_TIME|文件起始时间的键| 440 441### 轨道级别属性支持范围 442 443> **说明:** 444> 正常解析时才可以获取对应属性数据;如果文件信息错误或缺失,将导致解析异常,无法获取数据。 445> 辅助轨属性范围与实际媒体类型(音频、视频)保持一致。 446> 447> 数据类型及详细取值范围参考[媒体数据键值对](../../reference/apis-avcodec-kit/_codec_base.md#媒体数据键值对)。 448 449**表2** 轨道级别属性支持范围 450| 名称 | 描述 | 视频轨支持 | 音频轨支持 | 字幕轨支持 | 辅助轨支持 | 451| -- | -- | -- | -- | -- | -- | 452|OH_MD_KEY_CODEC_MIME|码流编解码器类型的键。|√|√|√|√| 453|OH_MD_KEY_TRACK_TYPE|码流媒体类型的键。|√|√|√|√| 454|OH_MD_KEY_TRACK_START_TIME|码流起始时间的键。|√|√|√|√| 455|OH_MD_KEY_BITRATE|码流比特率的键。|√|√|-|√| 456|OH_MD_KEY_LANGUAGE|码流语言类型的键。|√|√|-|√| 457|OH_MD_KEY_CODEC_CONFIG|编解码器特定数据的键,视频中表示传递参数集,音频中表示传递解码器的参数配置信息。|√|√|-|√| 458|OH_MD_KEY_WIDTH|视频流宽度的键。|√|-|-|√| 459|OH_MD_KEY_HEIGHT|视频流高度的键。|√|-|-|√| 460|OH_MD_KEY_FRAME_RATE|视频流帧率的键。|√|-|-|√| 461|OH_MD_KEY_ROTATION|视频流旋转角度的键。|√|-|-|√| 462|OH_MD_KEY_VIDEO_SAR|视频流样本长宽比的键。|√|-|-|√| 463|OH_MD_KEY_PROFILE|视频流编码档次,只针对h265码流使用。|√|-|-|√| 464|OH_MD_KEY_RANGE_FLAG|视频流视频YUV值域标志的键,只针对h265码流使用。|√|-|-|√| 465|OH_MD_KEY_COLOR_PRIMARIES|视频流视频色域的键,只针对h265码流使用。|√|-|-|√| 466|OH_MD_KEY_TRANSFER_CHARACTERISTICS|视频流视频传递函数的键,只针对h265码流使用。|√|-|-|√| 467|OH_MD_KEY_MATRIX_COEFFICIENTS|视频矩阵系数的键,只针对h265码流使用。|√|-|-|√| 468|OH_MD_KEY_VIDEO_IS_HDR_VIVID|视频流标记是否为HDR Vivid的键,只针对HDR Vivid码流使用。|√|-|-|√| 469|OH_MD_KEY_AUD_SAMPLE_RATE|音频流采样率的键。|-|√|-|√| 470|OH_MD_KEY_AUD_CHANNEL_COUNT|音频流通道数的键。|-|√|-|√| 471|OH_MD_KEY_CHANNEL_LAYOUT|音频流所需编码通道布局的键。|-|√|-|√| 472|OH_MD_KEY_AUDIO_SAMPLE_FORMAT|音频流样本格式的键。|-|√|-|√| 473|OH_MD_KEY_AAC_IS_ADTS|aac格式的键,只针对aac码流使用。|-|√|-|√| 474|OH_MD_KEY_BITS_PER_CODED_SAMPLE|音频流每个编码样本位数的键。|-|√|-|√| 475|OH_MD_KEY_REFERENCE_TRACK_IDS|媒体文件轨道间参考、被参考关系。|√|√|√|√| 476|OH_MD_KEY_TRACK_REFERENCE_TYPE|媒体文件辅助轨类型。|-|-|-|√| 477|OH_MD_KEY_TRACK_DESCRIPTION|媒体文件辅助轨描述信息。|-|-|-|√| 478