Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
MP4Handler
0.00% covered (danger)
0.00%
0 / 51
0.00% covered (danger)
0.00%
0 / 7
462
0.00% covered (danger)
0.00%
0 / 1
 getID3
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getImageSize
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
30
 getMetadataType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getWebType
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getStreamTypes
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
90
 getShortDesc
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
 getLongDesc
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace MediaWiki\TimedMediaHandler\Handlers\MP4Handler;
4
5use File;
6use MediaWiki\TimedMediaHandler\Handlers\ID3Handler\ID3Handler;
7
8/**
9 * MP4 handler
10 */
11class MP4Handler extends ID3Handler {
12
13    /**
14     * @param string $path
15     * @return array
16     */
17    protected function getID3( $path ) {
18        $id3 = parent::getID3( $path );
19        // Unset some parts of id3 that are too detailed and matroska specific:
20        unset( $id3['quicktime'] );
21        return $id3;
22    }
23
24    /**
25     * Get the "media size"
26     * @param File $file
27     * @param string $path
28     * @param string|false $metadata
29     * @return array|false
30     */
31    public function getImageSize( $file, $path, $metadata = false ) {
32        // Just return the size of the first video stream
33        if ( $metadata === false ) {
34            $metadata = $file->getMetadata();
35        }
36        $metadata = $this->unpackMetadata( $metadata );
37        if ( isset( $metadata['error'] ) ) {
38            return false;
39        }
40        if ( isset( $metadata['video']['resolution_x'] ) && isset( $metadata['video']['resolution_y'] ) ) {
41            return [
42                $metadata['video']['resolution_x'],
43                $metadata['video']['resolution_y']
44            ];
45        }
46        return [ false, false ];
47    }
48
49    /**
50     * @param File $image
51     * @return string
52     */
53    public function getMetadataType( $image ) {
54        return 'mp4';
55    }
56
57    /**
58     * @param File $file
59     * @return string
60     */
61    public function getWebType( $file ) {
62        // phpcs:disable Generic.Files.LineLength
63        /**
64         * h.264 profile types:
65         *  H.264 Simple baseline profile video (main and extended video compatible) level 3 and Low-Complexity AAC audio in MP4 container:
66         *  type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'
67         *
68         *  H.264 Extended profile video (baseline-compatible) level 3 and Low-Complexity AAC audio in MP4 container:
69         *  type='video/mp4; codecs="avc1.58A01E, mp4a.40.2"'
70         *
71         *  H.264 Main profile video level 3 and Low-Complexity AAC audio in MP4 container
72         *  type='video/mp4; codecs="avc1.4D401E, mp4a.40.2"'
73         *
74         *  H.264 ‘High’ profile video (incompatible with main, baseline, or extended profiles) level 3 and Low-Complexity AAC audio in MP4 container
75         *  type='video/mp4; codecs="avc1.64001E, mp4a.40.2"'
76         */
77        // phpcs:enable
78        // all h.264 encodes are currently simple profile
79        return 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';
80    }
81
82    /**
83     * @param File $file
84     * @return string[]|false
85     */
86    public function getStreamTypes( $file ) {
87        $streamTypes = [];
88        $metadata = $this->unpackMetadata( $file->getMetadata() );
89        if ( !$metadata || isset( $metadata['error'] ) ) {
90            return false;
91        }
92        if ( isset( $metadata['audio'] ) && $metadata['audio']['dataformat'] === 'mp4' ) {
93            if ( isset( $metadata['audio']['codec'] )
94                &&
95                strpos( $metadata['audio']['codec'], 'AAC' ) !== false
96            ) {
97                $streamTypes[] = 'AAC';
98            } else {
99                $streamTypes[] = $metadata['audio']['codec'];
100            }
101        }
102        // id3 gives 'V_VP8' for what we call VP8
103        if ( isset( $metadata['video'] ) && $metadata['video']['dataformat'] === 'quicktime' ) {
104            $streamTypes[] = 'h.264';
105        }
106
107        return $streamTypes;
108    }
109
110    /**
111     * @param File $file
112     * @return string
113     */
114    public function getShortDesc( $file ) {
115        $streamTypes = $this->getStreamTypes( $file );
116        if ( !$streamTypes ) {
117            return parent::getShortDesc( $file );
118        }
119        return wfMessage( 'timedmedia-mp4-short-video', implode( '/', $streamTypes )
120        )->timeperiodParams(
121            $this->getLength( $file )
122        )->text();
123    }
124
125    /**
126     * @param File $file
127     * @return string
128     */
129    public function getLongDesc( $file ) {
130        $streamTypes = $this->getStreamTypes( $file );
131        if ( !$streamTypes ) {
132            return parent::getLongDesc( $file );
133        }
134        return wfMessage(
135            'timedmedia-mp4-long-video',
136            implode( '/', $streamTypes )
137            )->timeperiodParams(
138                $this->getLength( $file )
139            )->bitrateParams(
140                $this->getBitRate( $file )
141            )->numParams(
142                $file->getWidth(),
143                $file->getHeight()
144            )->sizeParams(
145                $file->getSize()
146            )->text();
147    }
148
149}