Skip to content

Commit 2546582

Browse files
committed
🐛 Fix decode box error
1 parent 1382a30 commit 2546582

File tree

14 files changed

+207
-51
lines changed

14 files changed

+207
-51
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 1.4.2
4+
5+
- Fix: decode box error
6+
37
## 1.4.1
48

59
- Fix: `BaseBmffContext` constructor

example/bin/print_async_bmff_boxes_info.dart

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,28 @@ import 'package:bmff/bmff.dart';
22
import 'package:http/http.dart' as http;
33

44
Future<void> main(List<String> args) async {
5-
// final uri = Uri.parse('https://www.w3school.com.cn/i/movie.mp4');
6-
final uri = Uri.parse(
7-
'http://vfx.mtime.cn/Video/2019/03/18/mp4/190318231014076505.mp4');
5+
final urls = [
6+
'http://zuoye.free.fr/files/compare_still_1.heic.jpg',
7+
// 'http://vfx.mtime.cn/Video/2019/03/18/mp4/190318231014076505.mp4',
8+
// 'https://www.w3school.com.cn/i/movie.mp4',
9+
// 'https://cdn.jsdelivr.net/gh/ExampleAssets/ExampleAsset@master/preview_0.heic',
10+
];
11+
12+
for (final url in urls) {
13+
await showHttpBoxInfo(url);
14+
}
15+
}
16+
17+
Future<void> showHttpBoxInfo(String url) async {
18+
print('------------------ $url ------------------');
19+
20+
final uri = Uri.parse(url);
821
final bmff = await Bmff.asyncContext(AsyncBmffContextHttp(uri));
922
for (final box in bmff.childBoxes) {
1023
showBoxInfo(0, box);
1124
}
25+
26+
print('\n');
1227
}
1328

1429
void showBoxInfo(int level, AsyncBmffBox box) {
@@ -23,30 +38,53 @@ void showBoxInfo(int level, AsyncBmffBox box) {
2338
// part download http context
2439
class AsyncBmffContextHttp extends AsyncBmffContext {
2540
final Uri uri;
41+
final int maxCacheLength;
42+
43+
AsyncBmffContextHttp(
44+
this.uri, {
45+
this.maxCacheLength = 1024 * 1024 * 1,
46+
});
2647

27-
const AsyncBmffContextHttp(this.uri);
48+
List<int>? _bytes;
2849

2950
@override
3051
Future<List<int>> getRangeData(int start, int end) async {
52+
if (_bytes != null) {
53+
return _bytes!.sublist(start, end);
54+
}
55+
3156
final response = await http.get(uri, headers: {
3257
'Range': 'bytes=$start-${end - 1}',
3358
});
3459
if (response.statusCode != 206) {
3560
throw Exception(
36-
'Current http status code is ${response.statusCode}, not 206, not support range download');
61+
'Current http status code is ${response.statusCode}, not 206. '
62+
'The server not support range download');
3763
}
3864
final bytes = response.bodyBytes;
3965
return bytes;
4066
}
4167

4268
@override
4369
Future<int> lengthAsync() async {
44-
final response = await http.head(uri);
45-
final contentLength = response.headers['content-length'];
46-
if (contentLength != null) {
47-
return int.parse(contentLength);
70+
final response = await http.head(uri, headers: {
71+
'User-Agent': 'curl/7.79.1',
72+
'Accept': '*/*',
73+
'Host': uri.host,
74+
});
75+
final contentLengthList = response.headers.entries
76+
.where((element) => element.key.toLowerCase() == 'content-length');
77+
if (contentLengthList.isNotEmpty) {
78+
final contentLength = int.parse(contentLengthList.first.value);
79+
if (contentLength < maxCacheLength) {
80+
final response = await http.get(uri);
81+
_bytes = response.bodyBytes;
82+
}
83+
return contentLength;
4884
} else {
49-
throw Exception('content-length not found');
85+
final response = await http.get(uri);
86+
_bytes = response.bodyBytes;
87+
return response.bodyBytes.length;
5088
}
5189
}
5290
}

lib/src/bmff/async_bmff.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'dart:collection';
22

33
import 'package:bmff/bmff.dart';
4-
import 'package:bmff/src/box/box_factory.dart';
4+
import 'package:bmff/src/factory/box_factory.dart';
55

66
/// {@template bmff.async_bmff}
77
///

lib/src/bmff/bmff.dart

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:bmff/bmff.dart';
2-
import 'package:bmff/src/box/box_factory.dart';
2+
import 'package:bmff/src/factory/box_factory.dart';
3+
import 'package:bmff/src/box/full_box_type.dart';
34
import 'package:bmff/src/box/impl/bmff_impl.dart';
45

56
import 'stub.dart'
@@ -61,15 +62,24 @@ abstract class Bmff extends BoxContainer {
6162
/// {@macro bmff.bmff_for_web}
6263
///
6364
/// {@macro bmff.bmff_example}
64-
factory Bmff.file(String path) {
65+
factory Bmff.file(
66+
String path, {
67+
List<String> fullBoxtypes = fullBoxType,
68+
}) {
6569
return createBmffFromFile(path);
6670
}
6771

6872
/// Create [Bmff] from [bytes].
6973
///
7074
/// {@macro bmff.bmff_example}
71-
factory Bmff.memory(List<int> bytes) {
72-
return ContextBmffImpl(BmffMemoryContext(bytes));
75+
factory Bmff.memory(
76+
List<int> bytes, {
77+
List<String> fullBoxTypes = fullBoxType,
78+
}) {
79+
return ContextBmffImpl(BmffMemoryContext(
80+
bytes,
81+
fullBoxTypes: fullBoxTypes,
82+
));
7383
}
7484

7585
/// Type box

lib/src/bmff/io_impl.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import 'package:bmff/bmff.dart';
44
import 'package:bmff/src/box/full_box_type.dart';
55

66
/// {@macro bmff.createBmffFromFile}
7-
Bmff createBmffFromFile(String path) {
8-
return BmffIoContext(File(path)).bmff;
7+
Bmff createBmffFromFile(
8+
String path, {
9+
List<String> fullBoxTypes = fullBoxType,
10+
}) {
11+
return BmffIoContext(File(path), fullBoxTypes: fullBoxTypes).bmff;
912
}
1013

1114
/// {@template bmff.BmffIoContext}

lib/src/bmff/stub.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import 'package:bmff/bmff.dart';
2+
import 'package:bmff/src/box/full_box_type.dart';
23

34
///
45
/// {@template bmff.createBmffFromFile}
@@ -8,6 +9,7 @@ import 'package:bmff/bmff.dart';
89
/// For code compatibility, the web can call this method, but an error will be reported.
910
///
1011
/// {@endtemplate}
11-
Bmff createBmffFromFile(String path) {
12+
Bmff createBmffFromFile(String path,
13+
{List<String> fullBoxTypes = fullBoxType}) {
1214
throw UnimplementedError();
1315
}

lib/src/bmff/web_impl.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import 'package:bmff/bmff.dart';
2+
import 'package:bmff/src/box/full_box_type.dart';
23

34
/// {@macro bmff.createBmffFromFile}
4-
Bmff createBmffFromFile(String path) {
5+
Bmff createBmffFromFile(String path,
6+
{List<String> fullBoxTypes = fullBoxType}) {
57
throw UnimplementedError();
68
}

lib/src/box/box.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import 'dart:typed_data';
44
import 'package:bmff/bmff.dart';
55
import 'package:bmff/src/box_base.dart';
66

7-
import 'box_factory.dart';
7+
import '../factory/box_factory.dart';
88

99
/// {@template bmff.bmff_box}
1010
///
@@ -137,6 +137,10 @@ class AsyncBmffBox extends BmffBoxBase {
137137
Future<void> init() async {
138138
final children = await AsyncBoxFactory().decodeChildBoxes(this);
139139
childBoxes.addAll(children);
140+
141+
for (final child in children) {
142+
await child.init();
143+
}
140144
}
141145

142146
Future<void> updateForceFullBox(bool? forceFullBox) async {
@@ -147,9 +151,6 @@ class AsyncBmffBox extends BmffBoxBase {
147151
Future<void> _updateChildBoxes() async {
148152
childBoxes.clear();
149153
await init();
150-
for (final child in childBoxes) {
151-
await child._updateChildBoxes();
152-
}
153154
}
154155

155156
/// Get data of the box.

lib/src/box/full_box.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

lib/src/box/impl/bmff_impl.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import 'package:bmff/bmff.dart';
2-
import 'package:bmff/src/box/box_factory.dart';
2+
import 'package:bmff/src/factory/box_factory.dart';
33

44
class ContextBmffImpl extends Bmff {
55
/// {@macro bmff.bmff_example}

lib/src/context.dart

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,23 @@ abstract class AsyncBmffContext extends BaseBmffContext {
102102
Future<List<int>> getRangeData(int start, int end);
103103

104104
/// Create a [AsyncBmffContext] from [bytes].
105-
factory AsyncBmffContext.memory(List<int> bytes) {
106-
return MemoryAsyncBmffContext(
107-
() async => bytes.length,
108-
(start, end) async => bytes.sublist(start, end),
105+
factory AsyncBmffContext.bytes(
106+
List<int> bytes, {
107+
List<String> fullBoxTypes = fullBoxType,
108+
}) {
109+
return MemoryAsyncBmffContext(bytes, fullBoxTypes: fullBoxTypes);
110+
}
111+
112+
/// Create a [AsyncBmffContext] from [lengthAsyncGetter] and [rangeDataGetter].
113+
factory AsyncBmffContext.common(
114+
LengthGetter lengthAsyncGetter,
115+
RangeDataGetter rangeDataGetter, {
116+
List<String> fullBoxTypes = fullBoxType,
117+
}) {
118+
return _CommonAsyncBmffContext(
119+
lengthAsyncGetter,
120+
rangeDataGetter,
121+
fullBoxTypes: fullBoxTypes,
109122
);
110123
}
111124
}
@@ -115,9 +128,9 @@ abstract class AsyncBmffContext extends BaseBmffContext {
115128
/// The context of a BMFF file in memory.
116129
///
117130
/// {@endtemplate}
118-
class MemoryAsyncBmffContext extends AsyncBmffContext {
131+
class _CommonAsyncBmffContext extends AsyncBmffContext {
119132
/// {@macro bmff.MemoryAsyncBmffContext}
120-
const MemoryAsyncBmffContext(
133+
const _CommonAsyncBmffContext(
121134
this.lengthAsyncGetter,
122135
this.rangeDataGetter, {
123136
List<String> fullBoxTypes = fullBoxType,
@@ -139,3 +152,32 @@ class MemoryAsyncBmffContext extends AsyncBmffContext {
139152
return rangeDataGetter.call(start, end);
140153
}
141154
}
155+
156+
/// {@template bmff.MemoryAsyncBmffContext}
157+
/// The context of a BMFF file in memory.
158+
///
159+
/// This is a simple implementation of [AsyncBmffContext].
160+
///
161+
/// You can use [AsyncBmffContext.bytes] to use this.
162+
///
163+
/// {@endtemplate}
164+
class MemoryAsyncBmffContext extends AsyncBmffContext {
165+
/// {@macro bmff.MemoryAsyncBmffContext}
166+
const MemoryAsyncBmffContext(
167+
this.bytes, {
168+
List<String> fullBoxTypes = fullBoxType,
169+
}) : super(fullBoxTypes: fullBoxTypes);
170+
171+
/// The bytes of the context.
172+
final List<int> bytes;
173+
174+
@override
175+
Future<int> lengthAsync() {
176+
return Future.value(bytes.length);
177+
}
178+
179+
@override
180+
Future<List<int>> getRangeData(int start, int end) {
181+
return Future.value(bytes.sublist(start, end));
182+
}
183+
}

0 commit comments

Comments
 (0)