blob: 49d6bd7d872d881f198e97082f9246a9db37ed32 [file] [log] [blame]
// Copyright 2012 The Cobalt Authors. 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 COBALT_MEDIA_PROGRESSIVE_MP4_PARSER_H_
#define COBALT_MEDIA_PROGRESSIVE_MP4_PARSER_H_
#include "cobalt/media/progressive/avc_parser.h"
#include "cobalt/media/progressive/mp4_map.h"
#include "media/base/media_log.h"
namespace cobalt {
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 MP4Map 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 MP4Parser : public AVCParser {
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
// MP4Parser initialized with some basic state. If it doesn't make sense
// this returns an error status and |*parser| contains NULL.
static ::media::PipelineStatus Construct(
scoped_refptr<DataSourceReader> reader, const uint8* construction_header,
scoped_refptr<ProgressiveParser>* parser, MediaLog* media_log);
MP4Parser(scoped_refptr<DataSourceReader> reader, uint32 ftyp_atom_size,
MediaLog* media_log);
~MP4Parser() override;
// === ProgressiveParser implementation
bool ParseConfig() override;
scoped_refptr<AvcAccessUnit> GetNextAU(DemuxerStream::Type type) override;
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);
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<MP4Map> audio_map_;
scoped_refptr<MP4Map> 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
} // namespace cobalt
#endif // COBALT_MEDIA_PROGRESSIVE_MP4_PARSER_H_