File Coverage

blib/lib/FLV/Header.pm
Criterion Covered Total %
statement 56 56 100.0
branch 24 24 100.0
condition 2 6 33.3
subroutine 11 11 100.0
pod 6 6 100.0
total 99 103 96.1


line stmt bran cond sub pod time code
1             package FLV::Header;
2              
3 6     6   38 use warnings;
  6         11  
  6         216  
4 6     6   32 use strict;
  6         12  
  6         176  
5 6     6   464 use 5.008;
  6         24  
  6         235  
6 6     6   39 use Carp;
  6         13  
  6         680  
7              
8 6     6   45 use base 'FLV::Base';
  6         9  
  6         4686  
9              
10             our $VERSION = '0.24';
11              
12             =for stopwords FLVTool2
13              
14             =head1 NAME
15              
16             FLV::Header - Flash video file data structure
17              
18             =head1 LICENSE
19              
20             See L
21              
22             =head1 METHODS
23              
24             This is a subclass of FLV::Base.
25              
26             =over
27              
28             =item FLV::Header->new()
29              
30             Create a new instance.
31              
32             =item FLV::Header->create_from_body($body)
33              
34             Given an FLV::Body instance, construct a new header.
35              
36             =cut
37              
38             sub create_from_body
39             {
40 18     18 1 43 my $pkg = shift;
41 18   33     60 my $body = shift || croak 'no body specified';
42              
43 18         135 my $header = $pkg->new;
44              
45 18         112 for my $tag ($body->get_tags)
46             {
47 9173 100       40708 if ($tag->isa('FLV::VideoTag'))
    100          
48             {
49 3237         5275 $header->{has_video} = 1;
50             }
51             elsif ($tag->isa('FLV::AudioTag'))
52             {
53 5919         9241 $header->{has_audio} = 1;
54             }
55             }
56              
57 18         785 return $header;
58             }
59              
60              
61             =item $self->parse($fileinst)
62              
63             Takes a FLV::File instance and extracts the FLV header from the file
64             stream. This method throws exceptions if the stream is not a valid
65             FLV v1.0 or v1.1 file. The interpretation is a bit stricter than
66             other FLV parsers (for example FLVTool2).
67              
68             There is no return value.
69              
70             =cut
71              
72             sub parse
73             {
74 39     39 1 89 my $self = shift;
75 39         76 my $file = shift;
76              
77 39         182 my $content = $file->get_bytes(9);
78 36         371 my ($signature, $version, $flags, $offset) = unpack 'A3CCN', $content;
79              
80 36 100       143 if ($signature ne 'FLV')
81             {
82 1         7 die 'Not an FLV file at byte ' . $file->get_pos(-9);
83             }
84              
85 35 100       250 if ($version != 1)
86             {
87 1         9 die 'Internal error: I only understand FLV version 1';
88             }
89              
90             #if (0 != ($flags & 0xfa))
91 34 100       124 if (0 != ($flags & 0xf0))
92             {
93 1         5 die 'Reserved header flags are non-zero at byte ' . $file->get_pos(-5);
94             }
95              
96 33 100       102 if ($offset < 9)
97             {
98 1         5 die 'Illegal value for body offset at byte ' . $file->get_pos(-4);
99             }
100              
101 32 100       188 $self->{has_audio} = $flags & 0x04 ? 1 : undef;
102 32 100       138 $self->{has_video} = $flags & 0x01 ? 1 : undef;
103              
104             # Seek ahead in file
105 32 100       105 if ($offset > 9)
106             {
107 1         5 $file->get_bytes($offset - 9);
108             }
109              
110 32         105 return;
111             }
112              
113             =item $self->clone()
114              
115             Create an independent copy of this instance.
116              
117             =cut
118              
119             sub clone
120             {
121 8     8 1 20 my $self = shift;
122              
123 8         43 my $copy = FLV::Header->new;
124 8         28 for my $key (qw( has_audio has_video )) {
125 16         71 $copy->{$key} = $self->{$key};
126             }
127 8         30 return $copy;
128             }
129              
130             =item $self->serialize($filehandle)
131              
132             Serializes the in-memory FLV header. If that representation is not
133             complete, this throws an exception via croak(). Returns the number of
134             bytes written.
135              
136             =cut
137              
138             sub serialize
139             {
140 18     18 1 44 my $self = shift;
141 18   33     76 my $filehandle = shift || croak 'Please specify a filehandle';
142              
143 18 100       113 my $flags
    100          
144             = ($self->{has_audio} ? 0x04 : 0) | ($self->{has_video} ? 0x01 : 0);
145 18         176 my $header = pack 'A3CCN', 'FLV', 1, $flags, 9;
146 18         34 my $result = print {$filehandle} $header;
  18         321  
147 18 100       108 return $result ? length $header : 0;
148             }
149              
150             =item $self->has_video()
151              
152             Returns a boolean indicating if the FLV header predicts that video
153             data is enclosed in the stream.
154              
155             This value is not consulted internally.
156              
157             =cut
158              
159             sub has_video
160             {
161 21     21 1 35 my $self = shift;
162 21         107 return $self->{has_video};
163             }
164              
165             =item $self->has_audio()
166              
167             Returns a boolean indicating if the FLV header predicts that audio
168             data is enclosed in the stream.
169              
170             This value is not consulted internally.
171              
172             =cut
173              
174             sub has_audio
175             {
176 16     16 1 25 my $self = shift;
177 16         88 return $self->{has_audio};
178             }
179              
180             1;
181              
182             __END__