2014-07-14 21:35:57 +00:00
|
|
|
// Copyright 2014 The Chromium Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
// Media parser for a Widevine Media Format (WVM) file.
|
|
|
|
|
|
|
|
#ifndef MEDIA_FORMATS_WVM_WVM_MEDIA_PARSER_H_
|
|
|
|
#define MEDIA_FORMATS_WVM_WVM_MEDIA_PARSER_H_
|
|
|
|
|
|
|
|
#include <deque>
|
2014-09-15 20:11:37 +00:00
|
|
|
#include <map>
|
2014-07-14 21:35:57 +00:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2014-10-01 19:35:23 +00:00
|
|
|
|
2014-10-01 22:10:21 +00:00
|
|
|
#include "packager/base/memory/scoped_ptr.h"
|
|
|
|
#include "packager/media/base/aes_encryptor.h"
|
|
|
|
#include "packager/media/base/media_parser.h"
|
|
|
|
#include "packager/media/base/network_util.h"
|
|
|
|
#include "packager/media/filters/h264_byte_to_unit_stream_converter.h"
|
2014-07-14 21:35:57 +00:00
|
|
|
|
2014-09-19 20:41:13 +00:00
|
|
|
namespace edash_packager {
|
2014-07-14 21:35:57 +00:00
|
|
|
namespace media {
|
2014-09-30 16:58:43 +00:00
|
|
|
|
|
|
|
struct EncryptionKey;
|
|
|
|
class WidevineKeySource;
|
|
|
|
|
2014-07-14 21:35:57 +00:00
|
|
|
namespace wvm {
|
|
|
|
|
|
|
|
struct DemuxStreamIdMediaSample {
|
2014-09-16 19:55:49 +00:00
|
|
|
public:
|
|
|
|
DemuxStreamIdMediaSample();
|
|
|
|
~DemuxStreamIdMediaSample();
|
2014-09-30 21:52:21 +00:00
|
|
|
uint32_t demux_stream_id;
|
|
|
|
uint32_t parsed_audio_or_video_stream_id;
|
2014-07-14 21:35:57 +00:00
|
|
|
scoped_refptr<MediaSample> media_sample;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct PrevSampleData {
|
|
|
|
public:
|
2014-09-16 19:55:49 +00:00
|
|
|
PrevSampleData();
|
|
|
|
~PrevSampleData();
|
|
|
|
void Reset();
|
2014-07-14 21:35:57 +00:00
|
|
|
scoped_refptr<MediaSample> audio_sample;
|
|
|
|
scoped_refptr<MediaSample> video_sample;
|
2014-09-30 21:52:21 +00:00
|
|
|
uint32_t audio_stream_id;
|
|
|
|
uint32_t video_stream_id;
|
|
|
|
int64_t audio_sample_duration;
|
|
|
|
int64_t video_sample_duration;
|
2014-07-14 21:35:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class WvmMediaParser : public MediaParser {
|
|
|
|
public:
|
|
|
|
WvmMediaParser();
|
2014-09-16 19:55:49 +00:00
|
|
|
virtual ~WvmMediaParser();
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
// MediaParser implementation overrides.
|
|
|
|
virtual void Init(const InitCB& init_cb,
|
|
|
|
const NewSampleCB& new_sample_cb,
|
|
|
|
KeySource* decryption_key_source) OVERRIDE;
|
|
|
|
|
|
|
|
virtual void Flush() OVERRIDE;
|
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
virtual bool Parse(const uint8_t* buf, int size) OVERRIDE;
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
enum Tag {
|
|
|
|
CypherVersion = 0,
|
|
|
|
TrackOffset = 1,
|
|
|
|
TrackSize = 2,
|
|
|
|
TrackDuration = 3,
|
|
|
|
TrackBitRate = 4,
|
|
|
|
TrackTrickPlayRate = 5,
|
|
|
|
TrackAdaptationInterval = 6,
|
|
|
|
TrackFlags = 7,
|
|
|
|
VideoType = 8,
|
|
|
|
VideoProfile = 9,
|
|
|
|
VideoLevel = 10,
|
|
|
|
VideoWidth = 11,
|
|
|
|
VideoHeight = 12,
|
|
|
|
VideoTicksPerFrame = 13,
|
|
|
|
VideoBitRate = 14,
|
|
|
|
AudioType = 15,
|
|
|
|
AudioProfile = 16,
|
|
|
|
AudioNumChannels = 17,
|
|
|
|
AudioSampleFrequency = 18,
|
|
|
|
AudioBitRate = 19,
|
|
|
|
TrackVersion = 20,
|
|
|
|
Title = 21,
|
|
|
|
Copyright = 22,
|
|
|
|
ChapterIndex = 23,
|
|
|
|
TimeIndex = 24,
|
|
|
|
Thumbnail = 25,
|
|
|
|
ObjectSeqNum = 26,
|
|
|
|
ThumbnailOffset = 27,
|
|
|
|
ThumbnailSize = 28,
|
|
|
|
NumEntries = 29,
|
|
|
|
Chapters = 30,
|
|
|
|
VideoPixelWidth = 31,
|
|
|
|
VideoPixelHeight = 32,
|
|
|
|
FileSize = 33,
|
|
|
|
SparseDownloadUrl = 34,
|
|
|
|
SparseDownloadRangeTranslations = 35,
|
|
|
|
SparseDownloadMap = 36,
|
|
|
|
AudioSampleSize = 37,
|
|
|
|
Audio_EsDescriptor = 38,
|
|
|
|
AVCDecoderConfigurationRecord = 39,
|
|
|
|
Audio_EC3SpecificData = 40,
|
|
|
|
AudioIdentifier = 41,
|
|
|
|
VideoStreamId = 42,
|
|
|
|
VideoStreamType = 43,
|
|
|
|
AudioStreamId = 44,
|
|
|
|
AudioStreamType = 45,
|
|
|
|
Audio_DtsSpecificData = 46,
|
|
|
|
Audio_AC3SpecificData = 47,
|
|
|
|
Unset = 48
|
|
|
|
};
|
|
|
|
|
|
|
|
enum State {
|
|
|
|
StartCode1 = 0,
|
|
|
|
StartCode2,
|
|
|
|
StartCode3,
|
|
|
|
StartCode4,
|
|
|
|
PackHeader1,
|
|
|
|
PackHeader2,
|
|
|
|
PackHeader3,
|
|
|
|
PackHeader4,
|
|
|
|
PackHeader5,
|
|
|
|
PackHeader6,
|
|
|
|
PackHeader7,
|
|
|
|
PackHeader8,
|
|
|
|
PackHeader9,
|
|
|
|
PackHeader10,
|
|
|
|
PackHeaderStuffingSkip,
|
|
|
|
SystemHeader1,
|
|
|
|
SystemHeader2,
|
|
|
|
SystemHeaderSkip,
|
|
|
|
PesStreamId,
|
|
|
|
PesPacketLength1,
|
|
|
|
PesPacketLength2,
|
|
|
|
PesExtension1,
|
|
|
|
PesExtension2,
|
|
|
|
PesExtension3,
|
|
|
|
Pts1,
|
|
|
|
Pts2,
|
|
|
|
Pts3,
|
|
|
|
Pts4,
|
|
|
|
Pts5,
|
|
|
|
Dts1,
|
|
|
|
Dts2,
|
|
|
|
Dts3,
|
|
|
|
Dts4,
|
|
|
|
Dts5,
|
|
|
|
PesHeaderData,
|
|
|
|
PesPayload,
|
|
|
|
EsPayload,
|
|
|
|
PsmPayload,
|
|
|
|
EcmPayload,
|
|
|
|
IndexPayload,
|
|
|
|
Padding,
|
|
|
|
ProgramEnd
|
|
|
|
};
|
|
|
|
|
2014-09-30 16:58:43 +00:00
|
|
|
bool ProcessEcm();
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
// Index denotes 'search index' in the WVM content.
|
|
|
|
bool ParseIndexEntry();
|
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
bool DemuxNextPes(uint8_t* start, bool is_program_end);
|
2014-07-14 21:35:57 +00:00
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
void StartMediaSampleDemux(uint8_t* start);
|
2014-07-14 21:35:57 +00:00
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
template <typename T>
|
|
|
|
Tag GetTag(const uint8_t& tag,
|
|
|
|
const uint32_t& length,
|
|
|
|
const uint8_t* start_index,
|
|
|
|
T* value) {
|
|
|
|
if (length == sizeof(uint8_t)) {
|
|
|
|
*value = (uint8_t)(*start_index);
|
|
|
|
} else if (length == sizeof(int8_t)) {
|
|
|
|
*value = (int8_t)(*start_index);
|
|
|
|
} else if (length == sizeof(uint16_t)) {
|
|
|
|
*value = (uint16_t)(ntohsFromBuffer(start_index));
|
|
|
|
} else if (length == sizeof(int16_t)) {
|
|
|
|
*value = (int16_t)(ntohsFromBuffer(start_index));
|
|
|
|
} else if (length == sizeof(uint32_t)) {
|
|
|
|
*value = (uint32_t)(ntohlFromBuffer(start_index));
|
|
|
|
} else if (length == sizeof(int32_t)) {
|
|
|
|
*value = (int32_t)(ntohlFromBuffer(start_index));
|
|
|
|
} else if (length == sizeof(uint64_t)) {
|
|
|
|
*value = (uint64_t)(ntohllFromBuffer(start_index));
|
|
|
|
} else if (length == sizeof(int64_t)) {
|
|
|
|
*value = (int64_t)(ntohllFromBuffer(start_index));
|
2014-07-14 21:35:57 +00:00
|
|
|
} else {
|
|
|
|
*value = 0;
|
|
|
|
}
|
|
|
|
return Tag(tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Output();
|
|
|
|
|
2014-09-30 16:58:43 +00:00
|
|
|
bool GetAssetKey(const uint32_t asset_id, EncryptionKey* encryption_key);
|
|
|
|
|
2014-07-14 21:35:57 +00:00
|
|
|
// Callback invoked by the ES media parser
|
|
|
|
// to emit a new audio/video access unit.
|
2014-09-30 21:52:21 +00:00
|
|
|
void EmitSample(uint32_t parsed_audio_or_video_stream_id,
|
|
|
|
uint32_t stream_id,
|
|
|
|
scoped_refptr<MediaSample>& new_sample,
|
|
|
|
bool isLastSample);
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
void EmitPendingSamples();
|
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
bool EmitLastSample(uint32_t stream_id,
|
|
|
|
scoped_refptr<MediaSample>& new_sample);
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
// List of callbacks.t
|
|
|
|
InitCB init_cb_;
|
|
|
|
NewSampleCB new_sample_cb_;
|
|
|
|
|
|
|
|
// Whether |init_cb_| has been invoked.
|
|
|
|
bool is_initialized_;
|
|
|
|
// Internal content parsing state.
|
|
|
|
State parse_state_;
|
|
|
|
|
|
|
|
bool is_psm_needed_;
|
2014-09-30 21:52:21 +00:00
|
|
|
uint32_t skip_bytes_;
|
2014-07-14 21:35:57 +00:00
|
|
|
bool metadata_is_complete_;
|
2014-09-30 21:52:21 +00:00
|
|
|
uint8_t current_program_id_;
|
|
|
|
uint32_t pes_stream_id_;
|
|
|
|
uint32_t prev_pes_stream_id_;
|
|
|
|
uint16_t pes_packet_bytes_;
|
|
|
|
uint8_t pes_flags_1_;
|
|
|
|
uint8_t pes_flags_2_;
|
2014-09-30 16:58:43 +00:00
|
|
|
uint8_t prev_pes_flags_1_;
|
2014-09-30 21:52:21 +00:00
|
|
|
uint8_t pes_header_data_bytes_;
|
|
|
|
uint64_t timestamp_;
|
|
|
|
uint64_t pts_;
|
|
|
|
uint64_t dts_;
|
|
|
|
uint8_t index_program_id_;
|
2014-07-14 21:35:57 +00:00
|
|
|
scoped_refptr<MediaSample> media_sample_;
|
|
|
|
PrevSampleData prev_media_sample_data_;
|
|
|
|
H264ByteToUnitStreamConverter byte_to_unit_stream_converter_;
|
|
|
|
|
2014-09-30 21:52:21 +00:00
|
|
|
std::vector<uint8_t, std::allocator<uint8_t> > ecm_;
|
|
|
|
std::vector<uint8_t> psm_data_;
|
|
|
|
std::vector<uint8_t> index_data_;
|
|
|
|
std::map<std::string, uint32_t> program_demux_stream_map_;
|
2014-07-14 21:35:57 +00:00
|
|
|
int stream_id_count_;
|
|
|
|
std::vector<scoped_refptr<StreamInfo> > stream_infos_;
|
|
|
|
std::deque<DemuxStreamIdMediaSample> media_sample_queue_;
|
2014-09-30 21:52:21 +00:00
|
|
|
std::vector<uint8_t> sample_data_;
|
2014-09-30 16:58:43 +00:00
|
|
|
WidevineKeySource* decryption_key_source_;
|
|
|
|
AesCbcCtsDecryptor content_decryptor_;
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(WvmMediaParser);
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace wvm
|
|
|
|
} // namespace media
|
2014-09-19 20:41:13 +00:00
|
|
|
} // namespace edash_packager
|
2014-07-14 21:35:57 +00:00
|
|
|
|
|
|
|
#endif // MEDIA_FORMATS_WVM_WVM_MEDIA_PARSER_H_
|