File Coverage

blib/lib/FlashVideo/VideoPreferences/Quality.pm
Criterion Covered Total %
statement 42 43 97.6
branch 16 16 100.0
condition n/a
subroutine 7 7 100.0
pod 0 6 0.0
total 65 72 90.2


line stmt bran cond sub pod time code
1             # Part of get-flash-videos. See get_flash_videos for copyright.
2             package FlashVideo::VideoPreferences::Quality;
3              
4 2     2   9 use strict;
  2         5  
  2         1560  
5              
6             my %format_map = (
7             "240p" => [320, 240, "low"],
8             "240w" => [427, 240, "low"],
9             "480p" => [640, 480, "medium"],
10             "480w" => [854, 480, "medium"],
11             "576p" => [720, 576, "medium"],
12             "720p" => [1280, 720, "high"],
13             "1080p" => [1920, 1080, "high"],
14             );
15              
16             sub new {
17 3     3 0 6 my($class, $quality) = @_;
18              
19 3         12 return bless \$quality, $class;
20             }
21              
22             sub name {
23 5     5 0 282 my($self) = @_;
24 5         17 return $$self;
25             }
26              
27             sub choose {
28 4     4 0 30 my($self, @available) = @_;
29              
30             # To make it easier we take the total number of pixels in a resolution, this
31             # may be a bit confusing if someone prefers a widescreen version and we don't
32             # choose it, however they can always specify the precise format in that case.
33            
34             # TODO: If we have a video at a higher res than 1080p we won't choose it,
35             # maybe need to extend high (or add a very-high?).
36              
37 4         9 my $max_preferred_res = $self->quality_to_resolution($self->name);
38 4         10 my $max_preferred_size = $max_preferred_res->[0] * $max_preferred_res->[1];
39              
40 8         16 my @sorted =
41 10         11 sort { $a->[0] <=> $b->[0] }
42 4         6 map { my $r = $_->{resolution}; $r = $r->[0] * $r->[1]; [$r, $_] } @available;
  10         12  
  10         23  
43              
44 4 100       7 if(my @at_or_under_preferred = grep { $_->[0] <= $max_preferred_size } @sorted) {
  10         30  
45             # Max under preferred size
46 3         27 return $at_or_under_preferred[-1]->[1];
47             } else {
48             # Min over preferred size
49 1         7 return $sorted[0]->[1];
50             }
51             }
52              
53             sub format_to_resolution {
54 12     12 0 23 my($self, $name) = @_;
55 12 100       48 $name .= "p" if $name !~ /[a-z]$/i;
56              
57 12 100       53 if(my $resolution = $format_map{lc $name}) {
    100          
58 3         17 return $resolution;
59             } elsif(my $num = ($name =~ /(\d+)/)[0]) {
60             # Don't know about this, we'll return the number given as the size, in theory the
61             # height should be correct, which means if anything we'll be slightly under
62             # on the resolution.
63 1         5 my $resolution = [($num) x 2];
64 1         5 return [@$resolution, $self->resolution_to_quality($resolution)];
65             }
66              
67 8         64 die "Unknown format '$name'";
68             }
69              
70             sub quality_to_resolution {
71 11     11 0 21 my($self, $quality) = @_;
72              
73             # Allow specifying an actual resolution
74 11 100       36 if($quality =~ /^(\d+)x(\d+)$/) {
    100          
75 3         12 my $resolution = [$1, $2];
76 3         8 return [@$resolution, $self->resolution_to_quality($resolution)];
77              
78             # See if they specified a named format
79 8         18 } elsif(my $resolution = eval { $self->format_to_resolution($quality) }) {
80 1         7 return $resolution;
81              
82             } else {
83             # Search backwards until we find the name they specified.
84 7         26 for my $r(sort { ($b->[0]*$b->[1]) <=> ($a->[0]*$a->[1]) }
  98         155  
85             values %format_map) {
86 26 100       54 if($r->[2] eq lc $quality) {
87 7         28 return $r;
88             }
89             }
90             }
91              
92 0         0 die "Unknown quality '$quality'";
93             }
94              
95             sub resolution_to_quality {
96 9     9 0 387 my($self, $resolution) = @_;
97              
98 9         11 my $quality = "high";
99              
100 9         37 for my $r(sort { ($b->[0]*$b->[1]) <=> ($a->[0]*$a->[1]) }
  126         295  
101             values %format_map) {
102 63 100       143 $quality = $r->[2] if $r->[0] >= $resolution->[0];
103             }
104              
105 9         583 return $quality;
106             }
107              
108             1;