info: additional info for video streams
This commit is contained in:
parent
b60ebf6698
commit
a2dec02a14
3 changed files with 93 additions and 3 deletions
66
lib/model/video/h264.dart
Normal file
66
lib/model/video/h264.dart
Normal file
|
@ -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}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
||||||
|
|
||||||
import 'package:aves/model/entry.dart';
|
import 'package:aves/model/entry.dart';
|
||||||
import 'package:aves/model/video/channel_layouts.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/ref/languages.dart';
|
||||||
import 'package:aves/utils/math_utils.dart';
|
import 'package:aves/utils/math_utils.dart';
|
||||||
import 'package:fijkplayer/fijkplayer.dart';
|
import 'package:fijkplayer/fijkplayer.dart';
|
||||||
|
@ -9,7 +10,12 @@ import 'package:fijkplayer/fijkplayer.dart';
|
||||||
class StreamInfo {
|
class StreamInfo {
|
||||||
static const keyBitrate = 'bitrate';
|
static const keyBitrate = 'bitrate';
|
||||||
static const keyChannelLayout = 'channel_layout';
|
static const keyChannelLayout = 'channel_layout';
|
||||||
|
static const keyCodecLevel = 'codec_level';
|
||||||
static const keyCodecName = 'codec_name';
|
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 keyFpsDen = 'fps_den';
|
||||||
static const keyFpsNum = 'fps_num';
|
static const keyFpsNum = 'fps_num';
|
||||||
static const keyHeight = 'height';
|
static const keyHeight = 'height';
|
||||||
|
@ -18,6 +24,7 @@ class StreamInfo {
|
||||||
static const keySampleRate = 'sample_rate';
|
static const keySampleRate = 'sample_rate';
|
||||||
static const keySarDen = 'sar_den';
|
static const keySarDen = 'sar_den';
|
||||||
static const keySarNum = 'sar_num';
|
static const keySarNum = 'sar_num';
|
||||||
|
static const keyStartMicro = 'start_us';
|
||||||
static const keyTbrDen = 'tbr_den';
|
static const keyTbrDen = 'tbr_den';
|
||||||
static const keyTbrNum = 'tbr_num';
|
static const keyTbrNum = 'tbr_num';
|
||||||
static const keyType = 'type';
|
static const keyType = 'type';
|
||||||
|
@ -72,13 +79,16 @@ class StreamInfo {
|
||||||
|
|
||||||
static Map<String, String> formatStreamInfo(Map stream) {
|
static Map<String, String> formatStreamInfo(Map stream) {
|
||||||
final dir = <String, String>{};
|
final dir = <String, String>{};
|
||||||
|
final type = stream[keyType];
|
||||||
|
final codec = stream[keyCodecName];
|
||||||
for (final kv in stream.entries) {
|
for (final kv in stream.entries) {
|
||||||
final value = kv.value;
|
final value = kv.value;
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
final key = kv.key;
|
final key = kv.key;
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case keyIndex:
|
case keyCodecLevel:
|
||||||
case keyFpsNum:
|
case keyFpsNum:
|
||||||
|
case keyIndex:
|
||||||
case keySarNum:
|
case keySarNum:
|
||||||
case keyTbrNum:
|
case keyTbrNum:
|
||||||
case keyTbrDen:
|
case keyTbrDen:
|
||||||
|
@ -91,7 +101,21 @@ class StreamInfo {
|
||||||
dir['Channel Layout'] = ChannelLayouts.names[value] ?? 'unknown ($value)';
|
dir['Channel Layout'] = ChannelLayouts.names[value] ?? 'unknown ($value)';
|
||||||
break;
|
break;
|
||||||
case keyCodecName:
|
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;
|
break;
|
||||||
case keyFpsDen:
|
case keyFpsDen:
|
||||||
dir['Frame Rate'] = roundToPrecision(stream[keyFpsNum] / stream[keyFpsDen], decimals: 3).toString();
|
dir['Frame Rate'] = roundToPrecision(stream[keyFpsNum] / stream[keyFpsDen], decimals: 3).toString();
|
||||||
|
|
|
@ -211,7 +211,7 @@ packages:
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: aves
|
ref: aves
|
||||||
resolved-ref: "118fa08b30a7948df04d2692649b124a09ccb480"
|
resolved-ref: c217373cfe61fb17941571d17e38236765a8ec07
|
||||||
url: "git://github.com/deckerst/fijkplayer.git"
|
url: "git://github.com/deckerst/fijkplayer.git"
|
||||||
source: git
|
source: git
|
||||||
version: "0.8.7"
|
version: "0.8.7"
|
||||||
|
|
Loading…
Reference in a new issue