Report an error on encrypted stream without decryption

Change-Id: I784af57ca79aeb8a12245bd130f413ea6e3d04f1
This commit is contained in:
KongQun Yang 2017-05-31 11:14:11 -07:00
parent a430a20eaf
commit a251208a75
6 changed files with 88 additions and 2 deletions

View File

@ -95,6 +95,8 @@ Status Demuxer::Run() {
// info. // info.
if (all_streams_ready_ && output_handlers().empty()) if (all_streams_ready_ && output_handlers().empty())
return Status::OK; return Status::OK;
if (!init_event_status_.ok())
return init_event_status_;
if (!status.ok()) if (!status.ok())
return status; return status;
// Check if all specified outputs exists. // Check if all specified outputs exists.
@ -258,7 +260,14 @@ void Demuxer::ParserInitEvent(
stream_info->stream_type() != kStreamVideo) { stream_info->stream_type() != kStreamVideo) {
stream_info->set_language(iter->second); stream_info->set_language(iter->second);
} }
DispatchStreamInfo(stream_index, stream_info); if (stream_info->is_encrypted()) {
init_event_status_.SetError(
error::INVALID_ARGUMENT,
"A decryption key source is not provided for an encrypted stream.");
} else {
init_event_status_.Update(
DispatchStreamInfo(stream_index, stream_info));
}
} else { } else {
track_id_to_stream_index_map_[stream_info->track_id()] = track_id_to_stream_index_map_[stream_info->track_id()] =
kInvalidStreamIndex; kInvalidStreamIndex;
@ -278,6 +287,9 @@ bool Demuxer::NewSampleEvent(uint32_t track_id,
queued_samples_.push_back(QueuedSample(track_id, sample)); queued_samples_.push_back(QueuedSample(track_id, sample));
return true; return true;
} }
if (!init_event_status_.ok()) {
return false;
}
while (!queued_samples_.empty()) { while (!queued_samples_.empty()) {
if (!PushSample(queued_samples_.front().track_id, if (!PushSample(queued_samples_.front().track_id,
queued_samples_.front().sample)) { queued_samples_.front().sample)) {

View File

@ -33,7 +33,9 @@
'demuxer_unittest.cc', 'demuxer_unittest.cc',
], ],
'dependencies': [ 'dependencies': [
'../../testing/gmock.gyp:gmock',
'../../testing/gtest.gyp:gtest', '../../testing/gtest.gyp:gtest',
'../base/media_base.gyp:media_handler_test_base',
'../test/media_test.gyp:media_test_support', '../test/media_test.gyp:media_test_support',
'demuxer', 'demuxer',
] ]

View File

@ -140,6 +140,7 @@ class Demuxer : public MediaHandler {
bool cancelled_ = false; bool cancelled_ = false;
// Whether to dump stream info when it is received. // Whether to dump stream info when it is received.
bool dump_stream_info_ = false; bool dump_stream_info_ = false;
Status init_event_status_;
}; };
} // namespace media } // namespace media

View File

@ -6,16 +6,72 @@
#include "packager/media/demuxer/demuxer.h" #include "packager/media/demuxer/demuxer.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include "packager/media/base/fixed_key_source.h"
#include "packager/media/base/media_handler_test_base.h"
#include "packager/media/base/test/status_test_util.h"
#include "packager/media/test/test_data_util.h"
namespace shaka { namespace shaka {
namespace media { namespace media {
namespace {
TEST(DemuxerTest, FileNotFound) { using ::testing::_;
using ::testing::Return;
using ::testing::SetArgPointee;
class MockKeySource : public FixedKeySource {
public:
MOCK_METHOD2(GetKey,
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));
};
} // namespace
class DemuxerTest : public MediaHandlerTestBase {
protected:
EncryptionKey GetMockEncryptionKey() {
const uint8_t kKeyId[]{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
};
const uint8_t kKey[]{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
};
EncryptionKey encryption_key;
encryption_key.key_id.assign(kKeyId, kKeyId + sizeof(kKeyId));
encryption_key.key.assign(kKey, kKey + sizeof(kKey));
return encryption_key;
}
};
TEST_F(DemuxerTest, FileNotFound) {
Demuxer demuxer("file_not_exist.mp4"); Demuxer demuxer("file_not_exist.mp4");
EXPECT_EQ(error::FILE_FAILURE, demuxer.Run().error_code()); EXPECT_EQ(error::FILE_FAILURE, demuxer.Run().error_code());
} }
TEST_F(DemuxerTest, EncryptedContentWithoutKeySource) {
Demuxer demuxer(
GetAppTestDataFilePath("bear-640x360-v-cenc-golden.mp4").AsUTF8Unsafe());
ASSERT_OK(demuxer.SetHandler("video", some_handler()));
EXPECT_EQ(error::INVALID_ARGUMENT, demuxer.Run().error_code());
}
TEST_F(DemuxerTest, EncryptedContentWithKeySource) {
std::unique_ptr<MockKeySource> mock_key_source(new MockKeySource);
EXPECT_CALL(*mock_key_source, GetKey(_, _))
.WillOnce(
DoAll(SetArgPointee<1>(GetMockEncryptionKey()), Return(Status::OK)));
Demuxer demuxer(
GetAppTestDataFilePath("bear-640x360-v-cenc-golden.mp4").AsUTF8Unsafe());
demuxer.SetKeySource(std::move(mock_key_source));
ASSERT_OK(demuxer.SetHandler("video", some_handler()));
EXPECT_OK(demuxer.Run());
}
// TODO(kqyang): Add more tests. // TODO(kqyang): Add more tests.
} // namespace media } // namespace media

View File

@ -23,6 +23,18 @@ base::FilePath GetTestDataFilePath(const std::string& name) {
return file_path; return file_path;
} }
base::FilePath GetAppTestDataFilePath(const std::string& name) {
base::FilePath file_path;
CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
file_path = file_path.Append(FILE_PATH_LITERAL("packager"))
.Append(FILE_PATH_LITERAL("app"))
.Append(FILE_PATH_LITERAL("test"))
.Append(FILE_PATH_LITERAL("testdata"))
.AppendASCII(name);
return file_path;
}
std::vector<uint8_t> ReadTestDataFile(const std::string& name) { std::vector<uint8_t> ReadTestDataFile(const std::string& name) {
std::string buffer; std::string buffer;
CHECK(base::ReadFileToString(GetTestDataFilePath(name), &buffer)); CHECK(base::ReadFileToString(GetTestDataFilePath(name), &buffer));

View File

@ -17,6 +17,9 @@ namespace media {
// Returns a file path for a file in the media/test/data directory. // Returns a file path for a file in the media/test/data directory.
base::FilePath GetTestDataFilePath(const std::string& name); base::FilePath GetTestDataFilePath(const std::string& name);
// Returns a file path for a file in the media/app/test/testdata directory.
base::FilePath GetAppTestDataFilePath(const std::string& name);
// Reads a test file from media/test/data directory and returns its content. // Reads a test file from media/test/data directory and returns its content.
std::vector<uint8_t> ReadTestDataFile(const std::string& name); std::vector<uint8_t> ReadTestDataFile(const std::string& name);