Fixed various bugs:

- 17932674 Packager crashes when an incorrect key is provided to wvm.

- 17932293 Packager crashes if no key source is provided for wvm input.

- 17932868 StreamInfo is cast to AudioStreamInfo unconditionally and corrupts memory in wvm_media_parser

- 17932033 input: wvm --enable_fixed_key_decryption Segmentation Fault.

Change-Id: I7fc774c87a33314a4c92bc907f06c17f0c269a16
This commit is contained in:
Thomas Inskip 2014-10-09 12:56:51 -07:00
parent 9158f4a543
commit e7e86d684a
5 changed files with 61 additions and 43 deletions

View File

@ -26,12 +26,17 @@ KeySource::~KeySource() {}
Status KeySource::FetchKeys(const std::vector<uint8_t>& content_id, Status KeySource::FetchKeys(const std::vector<uint8_t>& content_id,
const std::string& policy) { const std::string& policy) {
// Do nothing for fixed key decryption. // Do nothing for fixed key encryption/decryption.
return Status::OK; return Status::OK;
} }
Status KeySource::FetchKeys(const std::vector<uint8_t>& pssh_data) { Status KeySource::FetchKeys(const std::vector<uint8_t>& pssh_data) {
// Do nothing for fixed key decryption. // Do nothing for fixed key encryption/decryption.
return Status::OK;
}
Status KeySource::FetchKeys(uint32_t asset_id) {
// Do nothing for fixed key encryption/decryption.
return Status::OK; return Status::OK;
} }

View File

@ -51,6 +51,12 @@ class KeySource {
/// @return OK on success, an error status otherwise. /// @return OK on success, an error status otherwise.
virtual Status FetchKeys(const std::vector<uint8_t>& pssh_data); virtual Status FetchKeys(const std::vector<uint8_t>& pssh_data);
/// Fetch keys for WVM decryption from the key server.
/// @param asset_id is the Widevine Classic asset ID for the content to be
/// decrypted.
/// @return OK on success, an error status otherwise.
virtual Status FetchKeys(uint32_t asset_id) OVERRIDE;
/// Get encryption key of the specified track type. /// Get encryption key of the specified track type.
/// @param track_type is the type of track for which retrieving the key. /// @param track_type is the type of track for which retrieving the key.
/// @param key is a pointer to the EncryptionKey which will hold the retrieved /// @param key is a pointer to the EncryptionKey which will hold the retrieved

View File

@ -37,7 +37,7 @@ class WidevineKeySource : public KeySource {
virtual Status FetchKeys(const std::vector<uint8_t>& content_id, virtual Status FetchKeys(const std::vector<uint8_t>& content_id,
const std::string& policy) OVERRIDE; const std::string& policy) OVERRIDE;
virtual Status FetchKeys(const std::vector<uint8_t>& pssh_data) OVERRIDE; virtual Status FetchKeys(const std::vector<uint8_t>& pssh_data) OVERRIDE;
virtual Status FetchKeys(uint32_t asset_id); virtual Status FetchKeys(uint32_t asset_id) OVERRIDE;
virtual Status GetKey(TrackType track_type, EncryptionKey* key) OVERRIDE; virtual Status GetKey(TrackType track_type, EncryptionKey* key) OVERRIDE;
virtual Status GetKey(const std::vector<uint8_t>& key_id, virtual Status GetKey(const std::vector<uint8_t>& key_id,

View File

@ -10,10 +10,10 @@
#include "packager/base/strings/string_number_conversions.h" #include "packager/base/strings/string_number_conversions.h"
#include "packager/media/base/audio_stream_info.h" #include "packager/media/base/audio_stream_info.h"
#include "packager/media/base/key_source.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
#include "packager/media/base/status.h" #include "packager/media/base/status.h"
#include "packager/media/base/video_stream_info.h" #include "packager/media/base/video_stream_info.h"
#include "packager/media/base/widevine_key_source.h"
#include "packager/media/formats/mp2t/adts_header.h" #include "packager/media/formats/mp2t/adts_header.h"
#define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \ #define HAS_HEADER_EXTENSION(x) ((x != 0xBC) && (x != 0xBE) && (x != 0xBF) \
@ -110,9 +110,7 @@ void WvmMediaParser::Init(const InitCB& init_cb,
DCHECK(!is_initialized_); DCHECK(!is_initialized_);
DCHECK(!init_cb.is_null()); DCHECK(!init_cb.is_null());
DCHECK(!new_sample_cb.is_null()); DCHECK(!new_sample_cb.is_null());
DCHECK(decryption_key_source); decryption_key_source_ = decryption_key_source;
decryption_key_source_ =
reinterpret_cast<WidevineKeySource*>(decryption_key_source);
init_cb_ = init_cb; init_cb_ = init_cb;
new_sample_cb_ = new_sample_cb; new_sample_cb_ = new_sample_cb;
} }
@ -756,8 +754,11 @@ bool WvmMediaParser::Output() {
if ((prev_pes_stream_id_ & kPesStreamIdVideoMask) == kPesStreamIdVideo) { if ((prev_pes_stream_id_ & kPesStreamIdVideoMask) == kPesStreamIdVideo) {
// Set data on the video stream from the NalUnitStream. // Set data on the video stream from the NalUnitStream.
std::vector<uint8_t> nal_unit_stream; std::vector<uint8_t> nal_unit_stream;
byte_to_unit_stream_converter_.ConvertByteStreamToNalUnitStream( if (!byte_to_unit_stream_converter_.ConvertByteStreamToNalUnitStream(
&sample_data_[0], sample_data_.size(), &nal_unit_stream); &sample_data_[0], sample_data_.size(), &nal_unit_stream)) {
LOG(ERROR) << "Could not convert h.264 byte stream sample";
return false;
}
media_sample_->set_data(nal_unit_stream.data(), nal_unit_stream.size()); media_sample_->set_data(nal_unit_stream.data(), nal_unit_stream.size());
if (!is_initialized_) { if (!is_initialized_) {
// Set extra data for video stream from AVC Decoder Config Record. // Set extra data for video stream from AVC Decoder Config Record.
@ -767,48 +768,50 @@ bool WvmMediaParser::Output() {
&decoder_config_record); &decoder_config_record);
for (uint32_t i = 0; i < stream_infos_.size(); i++) { for (uint32_t i = 0; i < stream_infos_.size(); i++) {
if (stream_infos_[i]->stream_type() == media::kStreamVideo && if (stream_infos_[i]->stream_type() == media::kStreamVideo &&
stream_infos_[i]->extra_data().empty()) { stream_infos_[i]->extra_data().empty()) {
stream_infos_[i]->set_extra_data(decoder_config_record); stream_infos_[i]->set_extra_data(decoder_config_record);
stream_infos_[i]->set_codec_string(VideoStreamInfo::GetCodecString( stream_infos_[i]->set_codec_string(VideoStreamInfo::GetCodecString(
kCodecH264, decoder_config_record[1], decoder_config_record[2], kCodecH264, decoder_config_record[1], decoder_config_record[2],
decoder_config_record[3])); decoder_config_record[3]));
} }
} }
} }
} else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) == } else if ((prev_pes_stream_id_ & kPesStreamIdAudioMask) ==
kPesStreamIdAudio) { kPesStreamIdAudio) {
// Set data on the audio stream from AdtsHeader. // Set data on the audio stream from AdtsHeader.
int frame_size = media::mp2t::AdtsHeader::GetAdtsFrameSize( int frame_size = media::mp2t::AdtsHeader::GetAdtsFrameSize(
&sample_data_[0], kAdtsHeaderMinSize); &sample_data_[0], kAdtsHeaderMinSize);
media::mp2t::AdtsHeader adts_header; media::mp2t::AdtsHeader adts_header;
const uint8_t* frame_ptr = &sample_data_[0]; const uint8_t* frame_ptr = &sample_data_[0];
std::vector<uint8_t> extra_data; std::vector<uint8_t> extra_data;
if (adts_header.Parse(frame_ptr, frame_size) && if (!adts_header.Parse(frame_ptr, frame_size) ||
(adts_header.GetAudioSpecificConfig(&extra_data))) { !adts_header.GetAudioSpecificConfig(&extra_data)) {
size_t header_size = adts_header.GetAdtsHeaderSize(frame_ptr, LOG(ERROR) << "Could not parse ADTS header";
frame_size); return false;
media_sample_->set_data(frame_ptr + header_size, }
frame_size - header_size); size_t header_size = adts_header.GetAdtsHeaderSize(frame_ptr,
if (!is_initialized_) { frame_size);
uint32_t sampling_frequency = adts_header.GetSamplingFrequency(); media_sample_->set_data(frame_ptr + header_size,
for (uint32_t i = 0; i < stream_infos_.size(); i++) { frame_size - header_size);
AudioStreamInfo* audio_stream_info = if (!is_initialized_) {
reinterpret_cast<AudioStreamInfo*>( for (uint32_t i = 0; i < stream_infos_.size(); i++) {
stream_infos_[i].get()); if (stream_infos_[i]->stream_type() == media::kStreamAudio &&
audio_stream_info->set_sampling_frequency(sampling_frequency); stream_infos_[i]->extra_data().empty()) {
// Set extra data and codec string on the audio stream from the // Set AudioStreamInfo fields using information from the ADTS
// AdtsHeader. // header.
if (stream_infos_[i]->stream_type() == media::kStreamAudio && AudioStreamInfo* audio_stream_info =
stream_infos_[i]->extra_data().empty()) { reinterpret_cast<AudioStreamInfo*>(
stream_infos_[i]->set_extra_data(extra_data); stream_infos_[i].get());
stream_infos_[i]->set_codec_string( audio_stream_info->set_sampling_frequency(
AudioStreamInfo::GetCodecString( adts_header.GetSamplingFrequency());
kCodecAAC, adts_header.GetObjectType())); audio_stream_info->set_extra_data(extra_data);
} audio_stream_info->set_codec_string(
} AudioStreamInfo::GetCodecString(
kCodecAAC, adts_header.GetObjectType()));
} }
} }
} }
}
if (!is_initialized_) { if (!is_initialized_) {
bool is_extra_data_in_stream_infos = true; bool is_extra_data_in_stream_infos = true;
@ -908,6 +911,10 @@ void WvmMediaParser::EmitSample(uint32_t parsed_audio_or_video_stream_id,
bool WvmMediaParser::GetAssetKey(const uint32_t asset_id, bool WvmMediaParser::GetAssetKey(const uint32_t asset_id,
EncryptionKey* encryption_key) { EncryptionKey* encryption_key) {
if (decryption_key_source_ == NULL) {
LOG(ERROR) << "Source content is encrypted, but decryption not enabled";
return false;
}
Status status = decryption_key_source_->FetchKeys(asset_id); Status status = decryption_key_source_->FetchKeys(asset_id);
if (!status.ok()) { if (!status.ok()) {
LOG(ERROR) << "Fetch Key(s) failed for AssetID = " << asset_id LOG(ERROR) << "Fetch Key(s) failed for AssetID = " << asset_id

View File

@ -20,8 +20,8 @@
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
class KeySource;
struct EncryptionKey; struct EncryptionKey;
class WidevineKeySource;
namespace wvm { namespace wvm {
@ -247,7 +247,7 @@ class WvmMediaParser : public MediaParser {
std::vector<scoped_refptr<StreamInfo> > stream_infos_; std::vector<scoped_refptr<StreamInfo> > stream_infos_;
std::deque<DemuxStreamIdMediaSample> media_sample_queue_; std::deque<DemuxStreamIdMediaSample> media_sample_queue_;
std::vector<uint8_t> sample_data_; std::vector<uint8_t> sample_data_;
WidevineKeySource* decryption_key_source_; KeySource* decryption_key_source_;
AesCbcCtsDecryptor content_decryptor_; AesCbcCtsDecryptor content_decryptor_;
DISALLOW_COPY_AND_ASSIGN(WvmMediaParser); DISALLOW_COPY_AND_ASSIGN(WvmMediaParser);