Nadav's Blog

MP4 files for Progressive download

Download Source


Preface
This article is addressed to developers dealing with MP4 streaming.
The article presents a sample code that patch an existing MP4 file making it progressive download enabled.

Introduction
MPEG-4 part 14 is a container file format mainly used to store multi-media content but can also be used to store arbitrary data, it is based on the QuickTime file format and extends it.

The file format in a nut shell
The MP4 Container is a hierarchical, each element consist of a basic entity named ATOM/BOX defining a type and the size of the segment in bytes, each ATOM can have child atoms resulting a compound hierarchy of objects, the basic ATOM structure is presented in figure 1 bellow.

Figure 1
Each atom defines a specialized data type ( indicated by 'uuid' ) and the byte range used for it's associated data ( indicated by 'size' ), the basic bytes range of each ATOM is 32bit and can be extended to 64bit variable, for simplicity, in this article 32bit atom size will be taken as granted.
A list of the registered ATOM/BOX types can be found here, For this use-case, the ATOMs 'mdat', 'moov' and 'stco' are of specific interest, figure 2 bellow present a common MP4 ATOM hierarchy.
Figure 2
The MP4 file is split in to three main chunks, header, data and metadata, the header indicate compatibility information, the data section contain the actual compressed multi-media payload, and the metadata section contain metadata related with the file including the file index, this index points into the data section indicating compressed data units file location and is mandatory for the file to be playable, this order is not coincidence, the 'data' section is created while recording, that is, while generating the compressed audio visual information, the metadata and in-specific the index can be resolved only after all the audio visual data was fully recorded, and thus, is added after the data section.

Progressive download is a pseudo streaming method, the player simulate streaming while progressively downloading the file and starting playback before the file was fully downloaded, obviously, playback cannot start w/o reading the metadata/index section, unfortunately, the metadata/index section is located at the end of the file, and this, force the player to fully download the file before playback can start.

This problem could have been resolved if the metadata/index section would have been read BEFORE the data section, this however, will require patching the MP4 file in a way reading only part of the file will be required.
To achieve that we will have to programmatically move the metadata/index section before the data section, Figure 3 bellow demonstrate what is needed to be done.
Figure 3
Moving the index before the data section by it-self is not enough, the data was moved and thus, it's file offset was changed, it is now needed to update the index offset by the size moved, to achieve that each 'stco' ATOM has to be iterated through and modified accordingly.

The sample code provided with this article is a simple console application that patch the MP4 file, relocating the 'moov' ATOM before the 'mdat' ATOM while updating the 'stco' offsets accordingly, I have tried to simplify it as much as possible making it simple and self-explained, please keep in mind that the code is for demonstration purpose only.

Download Source

Feedback: nadav@sophin.com