From a2dec02a14a4a41b8fa441b65e6d89793b928598 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Mon, 12 Apr 2021 16:41:58 +0900 Subject: [PATCH] info: additional info for video streams --- lib/model/video/h264.dart | 66 ++++++++++++++++++++++++++++++++++++ lib/model/video/streams.dart | 28 +++++++++++++-- pubspec.lock | 2 +- 3 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 lib/model/video/h264.dart diff --git a/lib/model/video/h264.dart b/lib/model/video/h264.dart new file mode 100644 index 000000000..8c8b3ad6d --- /dev/null +++ b/lib/model/video/h264.dart @@ -0,0 +1,66 @@ +class H264 { + static const profileConstrained = 1 << 9; + static const profileIntra = 1 << 11; + static const profileBaseline = 66; + static const profileConstrainedBaseline = 66 | profileConstrained; + static const profileMain = 77; + static const profileExtended = 88; + static const profileHigh = 100; + static const profileHigh10 = 110; + static const profileHigh10Intra = 110 | profileIntra; + static const profileHigh422 = 122; + static const profileHigh422Intra = 122 | profileIntra; + static const profileHigh444 = 144; + static const profileHigh444Predictive = 244; + static const profileHigh444Intra = 244 | profileIntra; + static const profileCAVLC_444 = 44; + + static String formatProfile(int profileIndex, int level) { + String profile; + switch (profileIndex) { + case profileBaseline: + profile = 'Baseline'; + break; + case profileConstrainedBaseline: + profile = 'Constrained Baseline'; + break; + case profileMain: + profile = 'Main'; + break; + case profileExtended: + profile = 'Extended'; + break; + case profileHigh: + profile = 'High'; + break; + case profileHigh10: + profile = 'High 10'; + break; + case profileHigh10Intra: + profile = 'High 10 Intra'; + break; + case profileHigh422: + profile = 'High 4:2:2'; + break; + case profileHigh422Intra: + profile = 'High 4:2:2 Intra'; + break; + case profileHigh444: + profile = 'High 4:4:4'; + break; + case profileHigh444Predictive: + profile = 'High 4:4:4 Predictive'; + break; + case profileHigh444Intra: + profile = 'High 4:4:4 Intra'; + break; + case profileCAVLC_444: + profile = 'CAVLC 4:4:4'; + break; + default: + return '$profileIndex'; + } + if (level < 10) return profile; + return '$profile Profile, Level ${level % 10 == 0 ? level ~/ 10 : level / 10}'; + } +} diff --git a/lib/model/video/streams.dart b/lib/model/video/streams.dart index 6e63c6faf..9002242d1 100644 --- a/lib/model/video/streams.dart +++ b/lib/model/video/streams.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:aves/model/entry.dart'; import 'package:aves/model/video/channel_layouts.dart'; +import 'package:aves/model/video/h264.dart'; import 'package:aves/ref/languages.dart'; import 'package:aves/utils/math_utils.dart'; import 'package:fijkplayer/fijkplayer.dart'; @@ -9,7 +10,12 @@ import 'package:fijkplayer/fijkplayer.dart'; class StreamInfo { static const keyBitrate = 'bitrate'; static const keyChannelLayout = 'channel_layout'; + static const keyCodecLevel = 'codec_level'; static const keyCodecName = 'codec_name'; + static const keyCodecPixelFormat = 'codec_pixel_format'; + static const keyCodecProfileId = 'codec_profile_id'; + static const keyDurationMicro = 'duration_us'; + static const keyFormat = 'format'; static const keyFpsDen = 'fps_den'; static const keyFpsNum = 'fps_num'; static const keyHeight = 'height'; @@ -18,6 +24,7 @@ class StreamInfo { static const keySampleRate = 'sample_rate'; static const keySarDen = 'sar_den'; static const keySarNum = 'sar_num'; + static const keyStartMicro = 'start_us'; static const keyTbrDen = 'tbr_den'; static const keyTbrNum = 'tbr_num'; static const keyType = 'type'; @@ -72,13 +79,16 @@ class StreamInfo { static Map formatStreamInfo(Map stream) { final dir = {}; + final type = stream[keyType]; + final codec = stream[keyCodecName]; for (final kv in stream.entries) { final value = kv.value; if (value != null) { final key = kv.key; switch (key) { - case keyIndex: + case keyCodecLevel: case keyFpsNum: + case keyIndex: case keySarNum: case keyTbrNum: case keyTbrDen: @@ -91,7 +101,21 @@ class StreamInfo { dir['Channel Layout'] = ChannelLayouts.names[value] ?? 'unknown ($value)'; break; case keyCodecName: - dir['Codec'] = _getCodecName(value); + dir['Codec'] = _getCodecName(value as String); + break; + case keyCodecPixelFormat: + if (type == typeVideo) { + dir['Pixel Format'] = (value as String).toUpperCase(); + } + break; + case keyCodecProfileId: + if (codec == 'h264') { + final profile = int.tryParse(value as String); + if (profile != null && profile != 0) { + final level = int.tryParse(stream[keyCodecLevel] as String); + dir['Codec Profile'] = H264.formatProfile(profile, level); + } + } break; case keyFpsDen: dir['Frame Rate'] = roundToPrecision(stream[keyFpsNum] / stream[keyFpsDen], decimals: 3).toString(); diff --git a/pubspec.lock b/pubspec.lock index 57079ea67..07c9789b6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -211,7 +211,7 @@ packages: description: path: "." ref: aves - resolved-ref: "118fa08b30a7948df04d2692649b124a09ccb480" + resolved-ref: c217373cfe61fb17941571d17e38236765a8ec07 url: "git://github.com/deckerst/fijkplayer.git" source: git version: "0.8.7"