Skip to content

Commit

Permalink
支持输出 mp4 rotate/width/height
Browse files Browse the repository at this point in the history
  • Loading branch information
clwu committed Feb 12, 2020
1 parent c589f8f commit 286726a
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 30 deletions.
24 changes: 22 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
# IphoneMp4Probe
# php-read-mp4info
返回 iPhone 拍摄的 mp4 视频的 rotate

用 php 实现了分析 mp4 视频文件的格式,但目前只实现了返回视频的的旋转度数。

![代码例子](https://gitee.com/uploads/images/2018/0419/121428_883f6648_556749.png "QQ图片20180419092233.png")

![手机旋转示例](https://gitee.com/uploads/images/2018/0419/121526_843b6a41_556749.png "QQ图片20180419121458.png")
![手机旋转示例](https://gitee.com/uploads/images/2018/0419/121526_843b6a41_556749.png "QQ图片20180419121458.png")

## composer.json
```json
"require": {
"clwu/php-read-mp4info": "v2.0.0"
}
```

```php
<?php
require('vendor/autoload.php');
var_dump(\Clwu\Mp4::getInfo('/tmp/faae8ca03b6e6c06cf47dad6dde46830.mp4'));


array(3) {
["rotate"]=> int(0)
["width"]=> int(960)
["height"]=> int(544)
}
```
10 changes: 5 additions & 5 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "clwu/mp4-rotate-probe",
"name": "clwu/php-read-mp4info",
"type": "library",
"description": "detect the rotation degrees of MP4 video",
"keywords": ["mp4","video","rotate", "rotation"],
"homepage": "https://gitee.com/clwu/IphoneMp4Probe",
"description": "detect the rotate/width/height ... of MP4 video",
"keywords": ["mp4","video","rotate", "rotation", "width", "height"],
"homepage": "https://github.com/clwu88/php-read-mp4info",
"license": "BSD-3-Clause",
"authors": [
{
Expand All @@ -17,7 +17,7 @@
},
"autoload": {
"psr-4": {
"Clwu\\Mp4\\": "src/Clwu/Mp4"
"Clwu\\": "src/Clwu"
}
}
}
82 changes: 59 additions & 23 deletions src/Clwu/Mp4.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

namespace Clwu\Mp4;
namespace Clwu;

class Mp4
{

/**
* 返回 mp4 视频的 rotate
* 返回 mp4 视频的 rotate/width/height ...
*
* @param $mp4_file_path
*
Expand All @@ -40,12 +40,15 @@ class Mp4
* @date Tue Apr 17 19:39:16 UTC 2018
*
* <code>
* echo \Clwu\Mp4::getRotate($argv[1]), PHP_EOL;
* var_dump( \Clwu\Mp4::getInfo($argv[1]) );
* </code>
*/
public static function getRotate($mp4_file_path)
public static function getInfo($mp4_file_path)
{
$rotate = 0;
$width = 0;
$height = 0;
$duration = 0;
$rotate = 0;
$decoded_len = 0; // 已经解码的文件长度
$err = 0;

Expand All @@ -68,10 +71,7 @@ public static function getRotate($mp4_file_path)

if ($is_extended_size) { // 64 bit extended size
$buffer = fread($fd, 8); // read in 64 bit extended size
// $size = array_pop( unpack('J', $buffer) ); // PHP Warning: unpack(): Invalid format type J
// v_v 公司用的PHP5.5 不支持 J 参数,用下面方式得到64bit的长度值,与上面一句注释了的代码一样效果
$num64 = unpack('N2', $buffer);
$size = ($num64[1] << 32) | $num64[2];
$size = self::unpack_u64($buffer);
}

if ("moov" == $type) {
Expand All @@ -88,23 +88,43 @@ public static function getRotate($mp4_file_path)
if (1 == $version) {
fread($fd, 8); // 64bit creation time
fread($fd, 8); // 64bit modification time
$d_len = 8;
} else {
fread($fd, 4); // 32bit creation time
fread($fd, 4); // 32bit modification time
$d_len = 4;
}
fread($fd, 4); // track id id号,不能重复且不能为0
fread($fd, 4); // reserved 保留位
fread($fd, 4); // duration track的时间长度
fread($fd, 8); // reserved 保留位
fread($fd, 2); // layer 视频层,默认为0,值小的在上层
fread($fd, 2); // alternate group track分组信息,默认为0表示该track未与其他track有群组关系
fread($fd, 2); // volume [8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0
fread($fd, 2); // reserved 保留位
$buffer = fread($fd, 36); // matrix 视频变换矩阵
fread($fd, 4); // width 宽
fread($fd, 4); // height 高,均为 [16.16] 格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高

$matrix = unpack('N9', $buffer); // unpack 没有参数可以转换为 signed long (always 32 bit, big endian byte order),在下面的比较中需要把 有符号-65536 转换为 无符号4294901760
fread($fd, 4); // track id id号,不能重复且不能为0
$_timescale = fread($fd, 4); // 用来指定文件媒体在1秒时间内的刻度值,可以理解为1秒长度的时间单元数
$_duration = fread($fd, $d_len); // duration track的时间长度
fread($fd, 8); // reserved 保留位
fread($fd, 2); // layer 视频层,默认为0,值小的在上层
fread($fd, 2); // alternate group track分组信息,默认为0表示该track未与其他track有群组关系
fread($fd, 2); // volume [8.8] 格式,如果为音频track,1.0(0x0100)表示最大音量;否则为0
fread($fd, 2); // reserved 保留位
$matrix = fread($fd, 36); // matrix 视频变换矩阵
$_width = fread($fd, 4); // width 宽
$_height = fread($fd, 4); // height 高,均为 [16.16] 格式值,与sample描述中的实际画面大小比值,用于播放时的展示宽高

$_width = current( unpack('n2', $_width) ); // [16.16] 格式值
$_height = current( unpack('n2', $_height) ); // [16.16] 格式值

// // 用duration和time scale值可以计算track时长
// $_timescale = current( unpack('N', $_timescale) );
// if (4 == $d_len) {
// $_duration = current( unpack('N', $_duration) );
// } else {
// $_duration = self::unpack_u64($_duration);
// }

// 有可能出现多次 tkhd,只取有效值
if ($_width || $_height) {
$width = $_width;
$height = $_height;
//$duration = $_duration / $_timescale; // 用duration和time scale值可以计算track时长
}

$matrix = unpack('N9', $matrix); // unpack 没有参数可以转换为 signed long (always 32 bit, big endian byte order),在下面的比较中需要把 有符号-65536 转换为 无符号4294901760
$display_matrix = [
[ $matrix[1], $matrix[2], $matrix[3] ],
[ $matrix[4], $matrix[5], $matrix[6] ],
Expand All @@ -131,7 +151,23 @@ public static function getRotate($mp4_file_path)
} while( $decoded_len < $total_len );

fclose($fd);
return $rotate;

return [
'rotate' => $rotate,
'width' => $width,
'height' => $height,
//'duration' => $duration,
// TODO: 更多的info 字段
];
}

private static function unpack_u64($str)
{
// $size = array_pop( unpack('J', $buffer) ); // PHP Warning: unpack(): Invalid format type J
// v_v 公司用的PHP5.5 不支持 J 参数,用下面方式得到64bit的长度值,与上面一句注释了的代码一样效果
$num64 = unpack('N2', $str);
$size = ($num64[1] << 32) | $num64[2];

return $size;
}
}

0 comments on commit 286726a

Please sign in to comment.