Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

h.264 video won't play on iOS

I have a video file encoded with h.264 that will not play on iOS, and I'd like to know why. Here's the HTML:

<video style="width: 480px; height: 360px;" autoplay controls>
    <source src="sample.mp4">
</video>

This video plays fine in a desktop browser, but on iOS devices I see an un-clickable Play icon with a slash through it. I've read that this means there's a problem with the video's encoding, but I'm not sure what the problem is.

I ran the video through MediaInfo:

General
Format                                   : MPEG-4
Format profile                           : Base Media
Codec ID                                 : isom
File size                                : 706 KiB
Duration                                 : 15s 256ms
Overall bit rate mode                    : Variable
Overall bit rate                         : 379 Kbps

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : [email protected]
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 6 frames
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 15s 250ms
Bit rate                                 : 311 Kbps
Width                                    : 480 pixels
Height                                   : 360 pixels
Display aspect ratio                     : 4:3
Frame rate mode                          : Constant
Frame rate                               : 24.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.075
Stream size                              : 578 KiB (82%)

Audio
ID                                       : 2
Format                                   : AAC
Format/Info                              : Advanced Audio Codec
Format profile                           : LC
Codec ID                                 : 40
Duration                                 : 15s 256ms
Bit rate mode                            : Variable
Bit rate                                 : 62.8 Kbps
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 44.1 KHz
Compression mode                         : Lossy
Stream size                              : 117 KiB (17%)

Also, I ran it through GSpot and got some additional info:

Container
isom: MP4 Base Media v1 [IS0 14496-12:2003]
- mp41: MP4 v1 [ISO 14496-1:ch13]

Can anyone tell me why this video won't play? I know I can simply re-encode the video, and if I do, it plays fine on iOS. But I'd like to know what the problem with the original file is.

For comparison, here's the MediaInfo analysis of a re-encoded version I made (this one works):

General
Format                                   : MPEG-4
Format profile                           : Base Media
Codec ID                                 : isom
File size                                : 990 KiB
Duration                                 : 15s 256ms
Overall bit rate mode                    : Variable
Overall bit rate                         : 532 Kbps
Writing application                      : Lavf53.19.0

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : [email protected]
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 4 frames
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 15s 250ms
Bit rate                                 : 414 Kbps
Width                                    : 480 pixels
Height                                   : 360 pixels
Display aspect ratio                     : 4:3
Frame rate mode                          : Constant
Frame rate                               : 24.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.100
Stream size                              : 771 KiB (78%)
Writing library                          : x264 core 118 r2085 8a62835
Encoding settings                        : cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x111 / me=hex / subme=6 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=12 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=24 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=22.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00

Audio
ID                                       : 2
Format                                   : AAC
Format/Info                              : Advanced Audio Codec
Format profile                           : LC
Codec ID                                 : 40
Duration                                 : 15s 256ms
Bit rate mode                            : Variable
Bit rate                                 : 111 Kbps
Maximum bit rate                         : 128 Kbps
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 44.1 KHz
Compression mode                         : Lossy
Stream size                              : 207 KiB (21%)

GSpot's info about this one's container is different (could that be why this one works?):

Container
isom: MP4 Base Media v1 [IS0 14496-12:2003]
- iso2: MP4 Base Media v2 [ISO 14496-12:2005]
- avc1: MP4 Base w/ AVC ext [ISO 14496-12:2005]
- mp41: MP4 v1 [ISO 14496-1:ch13]

The only other thing I can think of is the number of reference frames (I've read the max is 3), but the re-encoded version has 4 so I figure that's probably not it.

like image 823
user428517 Avatar asked Jan 14 '14 18:01

user428517


1 Answers

Found the solution to my own question:

The problem was that the video used the h.264 Main Profile level 5.1, while iOS only supports AVC level 3.1 (more info here).

I confirmed this by following these instructions to change the profile and level bytes using a hex editor. Search the file for avcC in ASCII or 61 76 63 43 in hex. The first byte is usually 01 and is unimportant to this purpose, but after that should be one of the following:

42 E0 – for Baseline Profile
4D 40 – for Main Profile
58 A0 – for Extended Profile
64 00 – for High Profile

The number after that is the level (without the decimal point) in hex, e.g.:

1F (31 in dec) is level 3.1
29 (41 in dec) is level 4.1
33 (51 in dec) is level 5.1

If you do a find and replace of all instances of the profile/level bytes (e.g., search 4D 40 33 and replace with the bytes you want--in my case 4D 40 1F), the video should now play on iOS. Note that many web help pages say iOS requires the Baseline profile, but that doesn't appear to be true. Main works fine as long as the AVC level is 3.1.

like image 191
user428517 Avatar answered Oct 10 '22 15:10

user428517