info: additional info for video streams

This commit is contained in:
Thibault Deckers 2021-04-12 16:41:58 +09:00
parent b60ebf6698
commit a2dec02a14
3 changed files with 93 additions and 3 deletions

66
lib/model/video/h264.dart Normal file
View 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}';
}
}

View file

@ -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();

View file

@ -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"