blob: bf7ea68f048b5a279574dc7cddc7cfd9ae4061f4 [file] [log] [blame]
/*
* Copyright 2012 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MEDIA_FILTERS_SHELL_MP4_PARSER_H_
#define MEDIA_FILTERS_SHELL_MP4_PARSER_H_
#include "media/filters/shell_avc_parser.h"
#include "media/filters/shell_mp4_map.h"
// If true the parser will save every atom it parses to disk. Note that since
// the parser is lazy and only parses what it needs to build the map and know
// the required video config information it is likely to not build a complete
// atom table for a given file.
#define SHELL_MP4_PARSER_DUMP_ATOMS 0
namespace media {
// How many bytes to download from the start of the atom? Should be large
// enough that we can extract all the data we need from the atom without
// second download (typically), but no larger. This is currently set at 16
// bytes for the 8 byte header + optional 8 byte size extension plus 20 bytes
// for the needed values within an mvhd header. We leave this is the header so
// that ShellMP4Map can re-use,
static const int kAtomDownload = 36;
// mp4 atom fourCC codes as big-endian unsigned ints
static const uint32 kAtomType_avc1 = 0x61766331; // skip in to subatom
static const uint32 kAtomType_avcC = 0x61766343; // download and parse
static const uint32 kAtomType_co64 = 0x636f3634; // cache in table
static const uint32 kAtomType_ctts = 0x63747473; // cache in table
static const uint32 kAtomType_dinf = 0x64696e66; // skip whole atom
static const uint32 kAtomType_dref = 0x64726566; // skip whole atom
static const uint32 kAtomType_esds = 0x65736473; // download and parse
static const uint32 kAtomType_ftyp = 0x66747970; // top of the file only
static const uint32 kAtomType_hdlr = 0x68646c72; // parse first 12 bytes
static const uint32 kAtomType_mdhd = 0x6d646864; // parse first 20 bytes
static const uint32 kAtomType_mdia = 0x6d646961; // container atom, no-op
static const uint32 kAtomType_minf = 0x6d696e66; // container atom, no-op
static const uint32 kAtomType_moov = 0x6d6f6f76; // container atom, no-op
static const uint32 kAtomType_mp4a = 0x6d703461; // parse first 10 bytes
static const uint32 kAtomType_mvhd = 0x6d766864; // parse first 20 bytes
static const uint32 kAtomType_smhd = 0x736d6862; // skip whole atom
static const uint32 kAtomType_stbl = 0x7374626c; // container atom, no-op
static const uint32 kAtomType_stco = 0x7374636f; // cache in table
static const uint32 kAtomType_stts = 0x73747473; // cache in table
static const uint32 kAtomType_stsc = 0x73747363; // cache in table
static const uint32 kAtomType_stsd = 0x73747364; // skip in to subatom
static const uint32 kAtomType_stss = 0x73747373; // cache in table
static const uint32 kAtomType_stsz = 0x7374737a; // cache in table
static const uint32 kAtomType_trak = 0x7472616b; // container atom, no-op
static const uint32 kAtomType_tkhd = 0x746b6864; // skip whole atom
static const uint32 kAtomType_vmhd = 0x766d6864; // skip whole atom
// TODO: mp4v!!
class ShellMP4Parser : public ShellAVCParser {
public:
// Attempts to make sense of the provided bytes of the top of a file as an
// flv, and if it does make sense returns PIPELINE_OK and |*parser| contains a
// ShellMP4Parser initialized with some basic state. If it doesn't make sense
// this returns an error status and |*parser| contains NULL.
static PipelineStatus Construct(scoped_refptr<ShellDataSourceReader> reader,
const uint8* construction_header,
scoped_refptr<ShellParser>* parser);
ShellMP4Parser(scoped_refptr<ShellDataSourceReader> reader,
uint32 ftyp_atom_size);
virtual ~ShellMP4Parser();
// === ShellParser implementation
virtual bool ParseConfig() OVERRIDE;
virtual scoped_refptr<ShellAU> GetNextAU(DemuxerStream::Type type) OVERRIDE;
virtual bool SeekTo(base::TimeDelta timestamp) OVERRIDE;
private:
bool ParseNextAtom();
bool ParseMP4_esds(uint64 atom_data_size);
bool ParseMP4_hdlr(uint64 atom_data_size, uint8* hdlr);
bool ParseMP4_mdhd(uint64 atom_data_size, uint8* mdhd);
bool ParseMP4_mp4a(uint64 atom_data_size, uint8* mp4a);
bool ParseMP4_mvhd(uint64 atom_data_size, uint8* mvhd);
base::TimeDelta TicksToTime(uint64 ticks, uint32 time_scale_hz);
uint64 TimeToTicks(base::TimeDelta time, uint32 time_scale_hz);
#if SHELL_MP4_PARSER_DUMP_ATOMS
void DumpAtomToDisk(uint32 four_cc, uint32 atom_size, uint64 atom_offset);
#endif
uint64 atom_offset_;
bool current_trak_is_video_;
bool current_trak_is_audio_;
uint32 current_trak_time_scale_;
base::TimeDelta current_trak_duration_;
uint32 video_time_scale_hz_;
base::TimeDelta one_video_tick_;
uint32 audio_time_scale_hz_;
base::TimeDelta audio_track_duration_;
base::TimeDelta video_track_duration_;
scoped_refptr<ShellMP4Map> audio_map_;
scoped_refptr<ShellMP4Map> video_map_;
uint32 audio_sample_;
uint32 video_sample_;
// for keeping buffers continuous across time scales
uint64 first_audio_hole_ticks_;
base::TimeDelta first_audio_hole_;
};
} // namespace media
#endif // MEDIA_FILTERS_SHELL_MP4_PARSER_H_