File Coverage

blib/lib/FLV/MetaTag.pm
Criterion Covered Total %
statement 89 91 97.8
branch 12 20 60.0
condition 4 5 80.0
subroutine 18 18 100.0
pod 7 7 100.0
total 130 141 92.2


line stmt bran cond sub pod time code
1             package FLV::MetaTag;
2              
3 6     6   37 use warnings;
  6         11  
  6         217  
4 6     6   31 use strict;
  6         11  
  6         332  
5 6     6   120 use 5.008;
  6         20  
  6         254  
6 6     6   45 use Carp;
  6         13  
  6         891  
7 6     6   41 use English qw(-no_match_vars);
  6         11  
  6         325  
8              
9 6     6   3951 use base 'FLV::Base';
  6         171  
  6         933  
10              
11 6     6   4585 use FLV::AMFReader;
  6         21  
  6         178  
12 6     6   3237 use FLV::AMFWriter;
  6         24  
  6         234  
13 6     6   73 use FLV::Util;
  6         12  
  6         1211  
14 6     6   39 use FLV::Tag;
  6         52  
  6         9617  
15              
16             our $VERSION = '0.24';
17              
18             =for stopwords FLVTool2 AMF
19              
20             =head1 NAME
21              
22             FLV::MetaTag - Flash video file data structure
23              
24             =head1 LICENSE
25              
26             See L
27              
28             =head1 DESCRIPTION
29              
30             As best I can tell, FLV meta tags are a pair of AMF data: one is the
31             event name and one is the payload. I learned that from looking at
32             sample FLV files and reading the FLVTool2 code.
33              
34             I've seen no specification for the meta tag, so this is all empirical
35             for me, unlike the other tags.
36              
37             =head1 METHODS
38              
39             This is a subclass of FLV::Base.
40              
41             =over
42              
43             =item $self->parse($fileinst)
44              
45             Takes a FLV::File instance and extracts an FLV meta tag from the file
46             stream. This method throws exceptions if the stream is not a valid
47             FLV v1.0 or v1.1 file.
48              
49             There is no return value.
50              
51             The majority of the work is done by FLV::AMFReader.
52              
53             =cut
54              
55             sub parse
56             {
57 31     31 1 73 my $self = shift;
58 31         48 my $file = shift;
59 31         146 my $datasize = shift;
60              
61 31         119 $self->{data} = [ $self->_deserialize($file->get_bytes($datasize)) ];
62 31         1087 return;
63             }
64              
65             sub _deserialize
66             {
67 39     39   82 my $self = shift;
68 39         70 my $content = shift;
69              
70 39         392 return FLV::AMFReader->new($content)->read_flv_meta();
71             }
72              
73             =item $self->clone()
74              
75             Create an independent copy of this instance.
76              
77             =cut
78              
79             sub clone
80             {
81 8     8 1 19 my $self = shift;
82              
83 8         40 my $copy = FLV::MetaTag->new;
84 8         58 FLV::Tag->copy_tag($self, $copy);
85 8         64 $copy->{data} = [ $self->_deserialize($self->serialize) ];
86 8         183 return $copy;
87             }
88              
89             =item $self->serialize()
90              
91             Returns a byte string representation of the tag data. Throws an
92             exception via croak() on error.
93              
94             =cut
95              
96             sub serialize
97             {
98 38     38 1 86 my $self = shift;
99              
100 38         476 my $content = FLV::AMFWriter->new()->write_flv_meta(@{ $self->{data} });
  38         1679  
101 38         683 return $content;
102             }
103              
104             =item $self->get_info()
105              
106             Returns a hash of FLV metadata. See FLV::Info for more details.
107              
108             =cut
109              
110             sub get_info
111             {
112 4     4 1 28 my ($pkg, @tags) = @_;
113              
114 4         10 my @records;
115             my %keys;
116 4         11 for my $tag (@tags)
117             {
118 4         18 my $data = $tag->{data}->[1];
119 4 50       19 if ($data)
120             {
121 4         9 my %fields;
122 4         9 for my $key (keys %{$data})
  4         36  
123             {
124 60         90 my $value = $data->{$key};
125 60 50       99 if (!defined $value)
126             {
127 0         0 $value = q{};
128             }
129 60         287 $value =~ s/ \A \s+ //xms;
130 60         179 $value =~ s/ \s+ \z //xms;
131 60         103 $fields{$key} = $value;
132 60         107 $keys{$key} = undef;
133             }
134 4         22 push @records, \%fields;
135             }
136             }
137 4         38 my %info = $pkg->_get_info('meta', \%keys, \@records);
138 4         117 return %info;
139             }
140              
141             =item $self->get_values();
142              
143             =item $self->get_value($key);
144              
145             =item $self->set_value($key, $value);
146              
147             These are convenience functions for interacting with an C
148             hash.
149              
150             C returns a hash of all metadata key-value pairs.
151             C returns a single value. C has no return
152             value.
153              
154             =cut
155              
156             sub get_values
157             {
158 18     18 1 37 my $self = shift;
159              
160 18 50       80 return if (!$self->{data});
161 18 50       30 return if (@{ $self->{data} } < 2);
  18         75  
162 18 50       88 return if ($self->{data}->[0] ne 'onMetaData');
163 18         39 return %{ $self->{data}->[1] };
  18         328  
164             }
165              
166             sub get_value
167             {
168 562     562 1 759 my $self = shift;
169 562         754 my $key = shift;
170              
171 562 100       1749 return if (!$self->{data});
172 539 50       618 return if (@{ $self->{data} } < 2);
  539         1384  
173 539 50       1377 return if ($self->{data}->[0] ne 'onMetaData');
174 539         2535 return $self->{data}->[1]->{$key};
175             }
176              
177             sub set_value
178             {
179 471     471 1 1087 my ($self, @keyvalues) = @_;
180              
181 471   100     1403 $self->{data} ||= [];
182 471 100 66     620 if (@{ $self->{data} } < 2 || $self->{data}->[0] ne 'onMetaData')
  471         2494  
183             {
184 23         41 unshift @{ $self->{data} }, 'onMetaData', {};
  23         102  
185             }
186              
187 471         1200 while (@keyvalues)
188             {
189 471         936 my ($key, $value) = splice @keyvalues, 0, 2;
190              
191 471 50       1725 if (defined $value)
192             {
193 471         1887 $self->{data}->[1]->{$key} = $value;
194             }
195             else
196             {
197 0         0 delete $self->{data}->[1]->{$key};
198             }
199             }
200              
201 471         1520 return;
202             }
203              
204             1;
205              
206             __END__