aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Bottomley <JBottomley@Parallels.com>2013-07-03 17:11:37 -0700
committerJames Bottomley <JBottomley@Parallels.com>2013-07-03 17:33:27 -0700
commitc740c47627fd22b12dc25a6e556414b8d54d3fe5 (patch)
tree629c57f86dd6a3846b01505710b1115583809616
parentb1cd1f266417ec374f7d73d59a2501f789986048 (diff)
downloadget-flash-videos-c740c47627fd22b12dc25a6e556414b8d54d3fe5.tar.gz
F4VDownloader: Update for large boxes
The spec file actually defines a large box type which wasn't implemented in the original F4VDownloader, leading it to fail on the new Channel4 F4V streams. Fix by adding support for this. Also update the methods to be non class, since they don't use any object data. Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--lib/FlashVideo/F4VDownloader.pm48
1 files changed, 29 insertions, 19 deletions
diff --git a/lib/FlashVideo/F4VDownloader.pm b/lib/FlashVideo/F4VDownloader.pm
index 0ca6a46..1b7ce14 100644
--- a/lib/FlashVideo/F4VDownloader.pm
+++ b/lib/FlashVideo/F4VDownloader.pm
@@ -38,20 +38,30 @@ use Data::AMF::Parser::AMF0;
sub read_box_header {
- my ($self, $s, $a) = @_;
+ my ($s, $a) = @_;
+ my $s_len = length($s);
($a->{len}, $a->{type}) = unpack('L>A4', $s);
+ $s = substr($s, 8);
+ $a->{headlen} = 8;
+ if ($a->{len} == 1) {
+ debug "LARGE BOX";
+ # large box size
+ ($a->{len}) = unpack('Q>', $s);
+ $s = substr($s, 8);
+ $a->{headlen} += 8;
+ }
debug "box header, size ".$a->{len}." type ".$a->{type};
- die "string not big enough (".length($s)." but should be >= ".$a->{len} if ($a->{len} > length($s));
- return substr($s, 8);
+ die "string not big enough (".$s_len." but should be >= ".$a->{len} if ($a->{len} > $s_len);
+ return $s;
}
sub read_segment_runtable {
- my ($self, $s, $a) = @_;
+ my ($s, $a) = @_;
my ($len, $totlen);
- $s = $self->read_box_header($s, $a);
+ $s = read_box_header($s, $a);
die "found wrong box ".$a->{type}." expecting asrt" if ($a->{type} ne 'asrt');
- $totlen = 8;
+ $totlen = $a->{headlen};
($a->{version},
$a->{flags},
$a->{qualityentrycount},
@@ -86,11 +96,11 @@ sub read_segment_runtable {
}
sub read_fragment_runtable {
- my ($self, $s, $a) = @_;
+ my ($s, $a) = @_;
my ($len, $totlen);
- $s = $self->read_box_header($s, $a);
+ $s = read_box_header($s, $a);
die "found wrong box ".$a->{type}." expecting afrt" if ($a->{type} ne 'afrt');
- $totlen = 8;
+ $totlen = $a->{headlen};
($a->{version},
$a->{flags},
$a->{timescale},
@@ -134,14 +144,14 @@ sub read_fragment_runtable {
}
sub read_bootstrap_box {
- my ($self, $s) = @_;
+ my ($s) = @_;
my $bb = {};
- $s = $self->read_box_header($s, $bb);
-
+ $s = read_box_header($s, $bb);
+
die "found wrong box ".$bb->{type}." expecting abst" if ($bb->{type} ne 'abst');
my ($len, $totlen, $packedbit);
- $totlen = 8;
+ $totlen = $bb->{headlen};
($bb->{version},
$bb->{flags},
$bb->{bootstrapinfoversion},
@@ -186,7 +196,7 @@ sub read_bootstrap_box {
my $i;
for ($i = 0; $i < $bb->{segmentruntablecount}; $i++) {
my $seg = {};
- $s = $self->read_segment_runtable($s, $seg);
+ $s = read_segment_runtable($s, $seg);
push $bb->{segmentruntable},$seg;
$totlen += $seg->{len};
}
@@ -196,7 +206,7 @@ sub read_bootstrap_box {
$bb->{fragmentruntable} = [()];
for ($i = 0; $i < $bb->{segmentruntablecount}; $i++) {
my $seg = {};
- $s = $self->read_fragment_runtable($s, $seg);
+ $s = read_fragment_runtable($s, $seg);
push $bb->{fragmentruntable},$seg;
$totlen += $seg->{len};
}
@@ -317,7 +327,7 @@ sub download {
info "Selected stream of resolution ".$media->{md}->{height}."x".$media->{md}->{width}." and bitrate ".$bitrate;
$media->{bootstrapInfo} = $manifest->{bootstrapInfo}->{$media->{bootstrapInfoId}};
- my $bb = $self->read_bootstrap_box(decode_base64($media->{bootstrapInfo}->{content}));
+ my $bb = read_bootstrap_box(decode_base64($media->{bootstrapInfo}->{content}));
debug 'Parsed media bootstrap data is '.Dumper($bb);
debug 'Parsed media metadata is '.Dumper($media);
@@ -388,10 +398,10 @@ sub download {
$bb = undef;
while(length($s) > 0) {
$a = {};
- $self->read_box_header($s, $a);
+ read_box_header($s, $a);
die "Fragment $frag too short" if (length($s) < $a->{len});
- $bb = $self->read_bootstrap_box($s) if ($a->{type} eq 'abst');
- $dat = substr($s, 8, $a->{len} - 8) if ($a->{type} eq 'mdat');
+ $bb = read_bootstrap_box($s) if ($a->{type} eq 'abst');
+ $dat = substr($s, $a->{headlen}, $a->{len} - $a->{headlen}) if ($a->{type} eq 'mdat');
$s = substr($s, $a->{len});
}
die "Didn't find the movie data box in fragment $frag" if (!defined($dat));