#!/usr/bin/perl
use warnings;
use strict;
use File::Temp qw(tempfile);
use File::Spec;
use Digest::MD5 qw(md5_hex);
use Test::More tests => 7 + 2 * 20; # general tests + number of samples * test per sample
BEGIN
{
use_ok('FLV::Info');
use_ok('FLV::FromSWF');
use_ok('FLV::ToSWF');
}
my @samples = (
{
swffile => File::Spec->catfile('t', 'samples', 'flash6.swf'),
flvfile => File::Spec->catfile('t', 'samples', 'flash6.flv'),
comparemeta => [qw(framerate audiocodecid videocodecid width height)],
},
{
swffile => File::Spec->catfile('t', 'samples', 'flash8.swf'),
flvfile => File::Spec->catfile('t', 'samples', 'flash8.flv'),
comparemeta => [qw(framerate audiocodecid videocodecid width height)],
},
);
my @cleanup;
# SWF -> FLV
{
my $converter = FLV::FromSWF->new();
eval { $converter->parse_swf('nosuchfile.swf'); };
like($@, qr/Can't open/, 'FromSWF parse non-existent file');
eval { $converter->save(File::Spec->catfile('nosuchdir/file.flv')); };
like($@, qr/Failed to write/, 'FromSWF impossible output filename');
}
for my $sample (@samples)
{
my $reader = FLV::Info->new();
$reader->parse($sample->{flvfile});
my $origflv = $reader->get_file();
my $converter = FLV::FromSWF->new();
$converter->parse_swf($sample->{swffile});
# Write the FLV back out as a temp file
my ($fh, $tempfilename) = tempfile();
die if (! -f $tempfilename);
push @cleanup, $tempfilename;
close $fh;
$converter->save($tempfilename);
my $rereader = FLV::Info->new();
$rereader->parse($tempfilename);
my $newflv = $rereader->get_file();
for my $key (@{$sample->{comparemeta}})
{
is($newflv->get_meta($key), $origflv->get_meta($key), 'FromSWF meta '.$key);
}
is(scalar $newflv->get_body()->get_video_frames(),
scalar $origflv->get_body()->get_video_frames(), 'FromSWF video frames');
#is(scalar $newflv->get_body()->get_audio_packets(),
# scalar $origflv->get_body()->get_audio_packets(), 'FromSWF audio packets');
is(scalar $newflv->get_body()->get_meta_tags(),
scalar $origflv->get_body()->get_meta_tags(), 'FromSWF meta tags');
#for my $tag ($newflv->get_body()->get_video_frames(),
# $origflv->get_body()->get_video_frames())
#{
# $tag->{data_length} = length $tag->{data};
# $tag->{data_md5} = md5_hex($tag->{data});
# delete $tag->{data};
#}
is_deeply([$newflv->get_body()->get_video_frames()],
[$origflv->get_body()->get_video_frames()],
'FromSWF detailed videotag comparison');
my @newaudio = map {$_->{data}} $newflv->get_body()->get_audio_packets();
my @origaudio = map {$_->{data}} $origflv->get_body()->get_audio_packets();
my $newaudio = join q{}, @newaudio;
my $origaudio = join q{}, @origaudio;
# Deliberately ignore omitted trailing audio
# This is an issue with the On2 Flix 8.004 FLV vs. SWF **encoders**
if (length $newaudio < length $origaudio)
{
$origaudio = substr $newaudio, 0, length $newaudio;
}
# This test is silly, given the above
is(length($newaudio), length($origaudio), 'FromSWF detailed audio data comparison');
is(md5_hex($newaudio), md5_hex($origaudio), 'FromSWF detailed audio data comparison');
}
# FLV -> SWF
{
my $converter = FLV::ToSWF->new();
eval { $converter->parse_flv('nosuchfile.flv'); };
like($@, qr/Failed to read FLV file/, 'ToSWF parse non-existent file');
eval { $converter->save(File::Spec->catfile('nosuchdir/file.swf')); };
like($@, qr/Can't open/, 'ToSWF impossible output filename');
}
for my $sample (@samples)
{
my $converter = FLV::ToSWF->new();
$converter->parse_flv($sample->{flvfile});
my $origflv = $converter->{flv};
# Write the SWF back out as a temp file
my ($fh, $tempswf) = tempfile();
die if (! -f $tempswf);
push @cleanup, $tempswf;
close $fh;
$converter->save($tempswf);
my $reconverter = FLV::FromSWF->new();
$reconverter->parse_swf($tempswf);
my $newflv = $reconverter->{flv};
for my $key (@{$sample->{comparemeta}})
{
is($newflv->get_meta($key), $origflv->get_meta($key), 'ToSWF meta '.$key);
}
is(scalar $newflv->get_body()->get_video_frames(),
scalar $origflv->get_body()->get_video_frames(), 'ToSWF video frames');
#is(scalar $newflv->get_body()->get_audio_packets(),
# scalar $origflv->get_body()->get_audio_packets(), 'ToSWF audio packets');
is(scalar $newflv->get_body()->get_meta_tags(),
scalar $origflv->get_body()->get_meta_tags(), 'ToSWF meta tags');
is_deeply([$newflv->get_body()->get_video_frames()],
[$origflv->get_body()->get_video_frames()],
'ToSWF detailed videotag comparison');
# Need to account for the fact that SWF lumps audio frames together but FLV doesn't
my @newaudio = map {$_->{data}} $newflv->get_body()->get_audio_packets();
my @origaudio = map {$_->{data}} $origflv->get_body()->get_audio_packets();
my $newaudio = join q{}, @newaudio;
my $origaudio = join q{}, @origaudio;
# Reconstitute orig with the same gaps as new
my $bytes = 0;
@origaudio = map {my $o=$bytes;$bytes+=length;substr $origaudio, $o, length} @newaudio;
if ($bytes < length $origaudio)
{
$origaudio[-1] .= substr $origaudio, $bytes;
}
## Even more detailed tests. Turn these on to find the exact error if the "detailed" tests below fail
if (0)
{
for my $i (0..$#newaudio)
{
is(length($newaudio[$i]), length($origaudio[$i]), 'length '.$i);
is(md5_hex($newaudio[$i]), md5_hex($origaudio[$i]), 'md5 '.$i);
}
}
is(length($newaudio), length($origaudio), 'detailed audio data comparison');
is(md5_hex($newaudio), md5_hex($origaudio), 'detailed audio data comparison');
}
END
{
# Delete temp files
unlink $_ for @cleanup;
}