Support generation of libpackager.so (shared_library)
Shared libpackager can be built by setting libpackager_type to shared_library, e.g. GYP_DEFINES='libpackager_type=shared_library' gclient runhooks ninja -C out/Debug will generate libpackager.so in out/Debug/lib directory. Here is a few other changes to make shared_library builds and tests pass: - Add several test parameters to packager.h, which is needed for testing. - Create a protoc.gypi from build/protoc.gypi but depending on protobuf_full_do_not_use instead of protobuf_lite, since we need protobuf_full_do_not_use for text parsing and generation of media info proto. Somehow shared_library build does not allow mixed use of protobuf_full_do_not_use and protobuf_lite. - Remove the use of LazyInstance in version/version.cc and use static variable directly. This is because LazyInstance needs AtExitManager which may not be easy to setup when calling GetVersion. - Allow skipping testPackageWvmInputWithoutStrippingParameterSetNalus with flag --shared_library, which is needed as shared_library build does not support --strip_parameter_set_nalus flag yet. Fixes #227 Change-Id: Iff05a50baa28134faa7218664c96114cb9e70329
This commit is contained in:
parent
2816a7262e
commit
05a5a41969
|
@ -17,7 +17,6 @@
|
||||||
#include "packager/app/stream_descriptor.h"
|
#include "packager/app/stream_descriptor.h"
|
||||||
#include "packager/app/vlog_flags.h"
|
#include "packager/app/vlog_flags.h"
|
||||||
#include "packager/app/widevine_encryption_flags.h"
|
#include "packager/app/widevine_encryption_flags.h"
|
||||||
#include "packager/base/at_exit.h"
|
|
||||||
#include "packager/base/command_line.h"
|
#include "packager/base/command_line.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/optional.h"
|
#include "packager/base/optional.h"
|
||||||
|
@ -26,7 +25,6 @@
|
||||||
#include "packager/base/strings/stringprintf.h"
|
#include "packager/base/strings/stringprintf.h"
|
||||||
#include "packager/media/file/file.h"
|
#include "packager/media/file/file.h"
|
||||||
#include "packager/packager.h"
|
#include "packager/packager.h"
|
||||||
#include "packager/version/version.h"
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
|
@ -34,6 +32,12 @@
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#endif // defined(OS_WIN)
|
#endif // defined(OS_WIN)
|
||||||
|
|
||||||
|
DEFINE_bool(dump_stream_info, false, "Dump demuxed stream info.");
|
||||||
|
DEFINE_bool(use_fake_clock_for_muxer,
|
||||||
|
false,
|
||||||
|
"Set to true to use a fake clock for muxer. With this flag set, "
|
||||||
|
"creation time and modification time in outputs are set to 0. "
|
||||||
|
"Should only be used for testing.");
|
||||||
DEFINE_bool(override_version,
|
DEFINE_bool(override_version,
|
||||||
false,
|
false,
|
||||||
"Override packager version in the generated outputs with "
|
"Override packager version in the generated outputs with "
|
||||||
|
@ -286,11 +290,16 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
||||||
hls_params.master_playlist_output = FLAGS_hls_master_playlist_output;
|
hls_params.master_playlist_output = FLAGS_hls_master_playlist_output;
|
||||||
hls_params.base_url = FLAGS_hls_base_url;
|
hls_params.base_url = FLAGS_hls_base_url;
|
||||||
|
|
||||||
|
TestParams& test_params = packaging_params.test_params;
|
||||||
|
test_params.dump_stream_info = FLAGS_dump_stream_info;
|
||||||
|
test_params.inject_fake_clock = FLAGS_use_fake_clock_for_muxer;
|
||||||
|
if (FLAGS_override_version)
|
||||||
|
test_params.injected_library_version = FLAGS_test_version;
|
||||||
|
|
||||||
return packaging_params;
|
return packaging_params;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PackagerMain(int argc, char** argv) {
|
int PackagerMain(int argc, char** argv) {
|
||||||
base::AtExitManager exit;
|
|
||||||
// Needed to enable VLOG/DVLOG through --vmodule or --v.
|
// Needed to enable VLOG/DVLOG through --vmodule or --v.
|
||||||
base::CommandLine::Init(argc, argv);
|
base::CommandLine::Init(argc, argv);
|
||||||
|
|
||||||
|
@ -299,7 +308,7 @@ int PackagerMain(int argc, char** argv) {
|
||||||
log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||||
CHECK(logging::InitLogging(log_settings));
|
CHECK(logging::InitLogging(log_settings));
|
||||||
|
|
||||||
google::SetVersionString(GetPackagerVersion());
|
google::SetVersionString(shaka::ShakaPackager::GetLibraryVersion());
|
||||||
google::SetUsageMessage(base::StringPrintf(kUsage, argv[0]));
|
google::SetUsageMessage(base::StringPrintf(kUsage, argv[0]));
|
||||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
|
@ -312,9 +321,6 @@ int PackagerMain(int argc, char** argv) {
|
||||||
return kArgumentValidationFailed;
|
return kArgumentValidationFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FLAGS_override_version)
|
|
||||||
SetPackagerVersionForTesting(FLAGS_test_version);
|
|
||||||
|
|
||||||
base::Optional<PackagingParams> packaging_params = GetPackagingParams();
|
base::Optional<PackagingParams> packaging_params = GetPackagingParams();
|
||||||
if (!packaging_params)
|
if (!packaging_params)
|
||||||
return kArgumentValidationFailed;
|
return kArgumentValidationFailed;
|
||||||
|
|
|
@ -9,16 +9,12 @@
|
||||||
#ifndef PACKAGER_APP_PACKAGER_UTIL_H_
|
#ifndef PACKAGER_APP_PACKAGER_UTIL_H_
|
||||||
#define PACKAGER_APP_PACKAGER_UTIL_H_
|
#define PACKAGER_APP_PACKAGER_UTIL_H_
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "packager/base/optional.h"
|
#include "packager/base/optional.h"
|
||||||
#include "packager/media/base/fourccs.h"
|
#include "packager/media/base/fourccs.h"
|
||||||
#include "packager/packager.h"
|
#include "packager/packager.h"
|
||||||
|
|
||||||
DECLARE_bool(dump_stream_info);
|
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
// TODO(kqyang): Should we consolidate XxxParams and XxxOptions?
|
// TODO(kqyang): Should we consolidate XxxParams and XxxOptions?
|
||||||
|
|
|
@ -454,6 +454,13 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
self._DiffGold(self.output[3], 'bear-640x360-a-wvm-golden.mp4')
|
self._DiffGold(self.output[3], 'bear-640x360-a-wvm-golden.mp4')
|
||||||
self._DiffGold(self.mpd_output, 'bear-wvm-golden.mpd')
|
self._DiffGold(self.mpd_output, 'bear-wvm-golden.mpd')
|
||||||
|
|
||||||
|
# TODO(kqyang): Fix shared_library not supporting strip_parameter_set_nalus
|
||||||
|
# problem.
|
||||||
|
@unittest.skipUnless(
|
||||||
|
test_env.options.static_libpackager,
|
||||||
|
'libpackager shared_library does not support '
|
||||||
|
'--strip_parameter_set_nalus flag.'
|
||||||
|
)
|
||||||
def testPackageWvmInputWithoutStrippingParameterSetNalus(self):
|
def testPackageWvmInputWithoutStrippingParameterSetNalus(self):
|
||||||
self.packager.Package(
|
self.packager.Package(
|
||||||
self._GetStreams(
|
self._GetStreams(
|
||||||
|
|
|
@ -27,6 +27,13 @@ SRC_DIR = os.path.join(SCRIPT_DIR, os.pardir, os.pardir)
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
|
|
||||||
parser.add_argument('--test_update_golden_files', default=0, type=int)
|
parser.add_argument('--test_update_golden_files', default=0, type=int)
|
||||||
|
|
||||||
|
parser.add_argument('--static_libpackager',
|
||||||
|
dest='static_libpackager', action='store_true')
|
||||||
|
parser.add_argument('--shared_libpackager',
|
||||||
|
dest='static_libpackager', action='store_false')
|
||||||
|
parser.set_defaults(static_libpackager=True)
|
||||||
|
|
||||||
parser.add_argument('--v')
|
parser.add_argument('--v')
|
||||||
parser.add_argument('--vmodule')
|
parser.add_argument('--vmodule')
|
||||||
# Overwrite the test to encryption key/iv specified in the command line.
|
# Overwrite the test to encryption key/iv specified in the command line.
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
'variables': {
|
'variables': {
|
||||||
# Compile as Chromium code to enable warnings and warnings-as-errors.
|
# Compile as Chromium code to enable warnings and warnings-as-errors.
|
||||||
'chromium_code': 1,
|
'chromium_code': 1,
|
||||||
|
'libpackager_type%': 'static_library',
|
||||||
},
|
},
|
||||||
'target_defaults': {
|
'target_defaults': {
|
||||||
'include_dirs': [
|
'include_dirs': [
|
||||||
|
|
|
@ -114,9 +114,8 @@
|
||||||
'proto_in_dir': '.',
|
'proto_in_dir': '.',
|
||||||
'proto_out_dir': 'packager/media/base',
|
'proto_out_dir': 'packager/media/base',
|
||||||
},
|
},
|
||||||
'includes': ['../../build/protoc.gypi'],
|
'includes': [
|
||||||
'dependencies': [
|
'../../protoc.gypi',
|
||||||
'../../third_party/protobuf/protobuf.gyp:protobuf_lite',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,9 @@
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
#include "packager/media/base/buffer_writer.h"
|
||||||
|
|
||||||
// TODO(kqyang): Move byte to unit stream convertion to muxer and make it a
|
// TODO(kqyang): Move byte to unit stream convertion to muxer and make it a
|
||||||
// muxer option.
|
// muxer option.
|
||||||
|
@ -21,9 +23,6 @@ DEFINE_bool(strip_parameter_set_nalus,
|
||||||
"frames. Note that avc1/hvc1 is generated if this flag is enabled; "
|
"frames. Note that avc1/hvc1 is generated if this flag is enabled; "
|
||||||
"otherwise avc3/hev1 is generated.");
|
"otherwise avc3/hev1 is generated.");
|
||||||
|
|
||||||
#include "packager/base/logging.h"
|
|
||||||
#include "packager/media/base/buffer_writer.h"
|
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,7 @@
|
||||||
'proto_in_dir': 'base',
|
'proto_in_dir': 'base',
|
||||||
'proto_out_dir': 'packager/mpd/base',
|
'proto_out_dir': 'packager/mpd/base',
|
||||||
},
|
},
|
||||||
'includes': ['../build/protoc.gypi'],
|
'includes': ['../protoc.gypi'],
|
||||||
'dependencies': [
|
|
||||||
# This target needs to depend on 'protobuf_full_do_not_use' to generate
|
|
||||||
# non-LITE (full) protobuf. We need full protobuf to serialize and
|
|
||||||
# deserialize human readable protobuf messages.
|
|
||||||
'../third_party/protobuf/protobuf.gyp:protobuf_full_do_not_use',
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'target_name': 'mpd_builder',
|
'target_name': 'mpd_builder',
|
||||||
|
|
|
@ -6,12 +6,10 @@
|
||||||
|
|
||||||
#include "packager/packager.h"
|
#include "packager/packager.h"
|
||||||
|
|
||||||
#include <gflags/gflags.h>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "packager/app/libcrypto_threading.h"
|
#include "packager/app/libcrypto_threading.h"
|
||||||
#include "packager/app/packager_util.h"
|
#include "packager/app/packager_util.h"
|
||||||
#include "packager/app/stream_descriptor.h"
|
#include "packager/app/stream_descriptor.h"
|
||||||
|
#include "packager/base/at_exit.h"
|
||||||
#include "packager/base/files/file_path.h"
|
#include "packager/base/files/file_path.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/path_service.h"
|
#include "packager/base/path_service.h"
|
||||||
|
@ -40,13 +38,7 @@
|
||||||
#include "packager/mpd/base/media_info.pb.h"
|
#include "packager/mpd/base/media_info.pb.h"
|
||||||
#include "packager/mpd/base/mpd_builder.h"
|
#include "packager/mpd/base/mpd_builder.h"
|
||||||
#include "packager/mpd/base/simple_mpd_notifier.h"
|
#include "packager/mpd/base/simple_mpd_notifier.h"
|
||||||
|
#include "packager/version/version.h"
|
||||||
DEFINE_bool(dump_stream_info, false, "Dump demuxed stream info.");
|
|
||||||
DEFINE_bool(use_fake_clock_for_muxer,
|
|
||||||
false,
|
|
||||||
"Set to true to use a fake clock for muxer. With this flag set, "
|
|
||||||
"creation time and modification time in outputs are set to 0. "
|
|
||||||
"Should only be used for testing.");
|
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
|
@ -124,7 +116,7 @@ bool ValidateStreamDescriptor(bool dump_stream_info,
|
||||||
const bool output_specified =
|
const bool output_specified =
|
||||||
!descriptor.output.empty() || !descriptor.segment_template.empty();
|
!descriptor.output.empty() || !descriptor.segment_template.empty();
|
||||||
if (!output_specified) {
|
if (!output_specified) {
|
||||||
if (!FLAGS_dump_stream_info) {
|
if (!dump_stream_info) {
|
||||||
LOG(ERROR) << "Stream output not specified.";
|
LOG(ERROR) << "Stream output not specified.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +193,8 @@ bool ValidateParams(const PackagingParams& packaging_params,
|
||||||
"stream descriptors.";
|
"stream descriptors.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ValidateStreamDescriptor(FLAGS_dump_stream_info, descriptor))
|
if (!ValidateStreamDescriptor(packaging_params.test_params.dump_stream_info,
|
||||||
|
descriptor))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (packaging_params.output_media_info && !on_demand_dash_profile) {
|
if (packaging_params.output_media_info && !on_demand_dash_profile) {
|
||||||
|
@ -380,7 +373,8 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
||||||
if (stream_iter->input != previous_input) {
|
if (stream_iter->input != previous_input) {
|
||||||
// New remux job needed. Create demux and job thread.
|
// New remux job needed. Create demux and job thread.
|
||||||
std::unique_ptr<Demuxer> demuxer(new Demuxer(stream_iter->input));
|
std::unique_ptr<Demuxer> demuxer(new Demuxer(stream_iter->input));
|
||||||
demuxer->set_dump_stream_info(FLAGS_dump_stream_info);
|
demuxer->set_dump_stream_info(
|
||||||
|
packaging_params.test_params.dump_stream_info);
|
||||||
if (packaging_params.decryption_params.key_provider !=
|
if (packaging_params.decryption_params.key_provider !=
|
||||||
KeyProvider::kNone) {
|
KeyProvider::kNone) {
|
||||||
std::unique_ptr<KeySource> decryption_key_source(
|
std::unique_ptr<KeySource> decryption_key_source(
|
||||||
|
@ -409,7 +403,8 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
||||||
|
|
||||||
std::shared_ptr<Muxer> muxer(
|
std::shared_ptr<Muxer> muxer(
|
||||||
CreateOutputMuxer(stream_muxer_options, output_format));
|
CreateOutputMuxer(stream_muxer_options, output_format));
|
||||||
if (FLAGS_use_fake_clock_for_muxer) muxer->set_clock(fake_clock);
|
if (packaging_params.test_params.inject_fake_clock)
|
||||||
|
muxer->set_clock(fake_clock);
|
||||||
|
|
||||||
std::unique_ptr<MuxerListener> muxer_listener;
|
std::unique_ptr<MuxerListener> muxer_listener;
|
||||||
DCHECK(!(packaging_params.output_media_info && mpd_notifier));
|
DCHECK(!(packaging_params.output_media_info && mpd_notifier));
|
||||||
|
@ -577,7 +572,8 @@ ShakaPackager::~ShakaPackager() {}
|
||||||
Status ShakaPackager::Initialize(
|
Status ShakaPackager::Initialize(
|
||||||
const PackagingParams& packaging_params,
|
const PackagingParams& packaging_params,
|
||||||
const std::vector<StreamDescriptor>& stream_descriptors) {
|
const std::vector<StreamDescriptor>& stream_descriptors) {
|
||||||
|
// Needed by base::WorkedPool used in ThreadedIoFile.
|
||||||
|
static base::AtExitManager exit;
|
||||||
static media::LibcryptoThreading libcrypto_threading;
|
static media::LibcryptoThreading libcrypto_threading;
|
||||||
|
|
||||||
if (internal_)
|
if (internal_)
|
||||||
|
@ -586,6 +582,11 @@ Status ShakaPackager::Initialize(
|
||||||
if (!media::ValidateParams(packaging_params, stream_descriptors))
|
if (!media::ValidateParams(packaging_params, stream_descriptors))
|
||||||
return Status(error::INVALID_ARGUMENT, "Invalid packaging params.");
|
return Status(error::INVALID_ARGUMENT, "Invalid packaging params.");
|
||||||
|
|
||||||
|
if (!packaging_params.test_params.injected_library_version.empty()) {
|
||||||
|
SetPackagerVersionForTesting(
|
||||||
|
packaging_params.test_params.injected_library_version);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<PackagerInternal> internal(new PackagerInternal);
|
std::unique_ptr<PackagerInternal> internal(new PackagerInternal);
|
||||||
|
|
||||||
ChunkingOptions chunking_options =
|
ChunkingOptions chunking_options =
|
||||||
|
@ -680,4 +681,8 @@ void ShakaPackager::Cancel() {
|
||||||
job->demuxer()->Cancel();
|
job->demuxer()->Cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ShakaPackager::GetLibraryVersion() {
|
||||||
|
return GetPackagerVersion();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
'targets': [
|
'targets': [
|
||||||
{
|
{
|
||||||
'target_name': 'libpackager',
|
'target_name': 'libpackager',
|
||||||
'type': 'static_library',
|
'type': '<(libpackager_type)',
|
||||||
'sources': [
|
'sources': [
|
||||||
'packager.cc',
|
'packager.cc',
|
||||||
'packager.h',
|
'packager.h',
|
||||||
|
@ -37,7 +37,15 @@
|
||||||
'media/trick_play/trick_play.gyp:trick_play',
|
'media/trick_play/trick_play.gyp:trick_play',
|
||||||
'mpd/mpd.gyp:mpd_builder',
|
'mpd/mpd.gyp:mpd_builder',
|
||||||
'third_party/boringssl/boringssl.gyp:boringssl',
|
'third_party/boringssl/boringssl.gyp:boringssl',
|
||||||
'third_party/gflags/gflags.gyp:gflags',
|
'version/version.gyp:version',
|
||||||
|
],
|
||||||
|
'conditions': [
|
||||||
|
['libpackager_type=="shared_library"', {
|
||||||
|
'defines': [
|
||||||
|
'SHARED_LIBRARY_BUILD',
|
||||||
|
'SHAKA_IMPLEMENTATION',
|
||||||
|
],
|
||||||
|
}],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -69,7 +77,9 @@
|
||||||
'app/widevine_encryption_flags.h',
|
'app/widevine_encryption_flags.h',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
|
'base/base.gyp:base',
|
||||||
'libpackager',
|
'libpackager',
|
||||||
|
'media/file/file.gyp:file',
|
||||||
'third_party/gflags/gflags.gyp:gflags',
|
'third_party/gflags/gflags.gyp:gflags',
|
||||||
],
|
],
|
||||||
'conditions': [
|
'conditions': [
|
||||||
|
@ -102,9 +112,10 @@
|
||||||
'packager_test.cc',
|
'packager_test.cc',
|
||||||
],
|
],
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
|
'base/base.gyp:base',
|
||||||
'libpackager',
|
'libpackager',
|
||||||
'media/test/media_test.gyp:media_test_support',
|
|
||||||
'testing/gtest.gyp:gtest',
|
'testing/gtest.gyp:gtest',
|
||||||
|
'testing/gtest.gyp:gtest_main',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,29 @@
|
||||||
// TODO(kqyang): Refactor status.h and move it under packager/.
|
// TODO(kqyang): Refactor status.h and move it under packager/.
|
||||||
#include "packager/media/base/status.h"
|
#include "packager/media/base/status.h"
|
||||||
|
|
||||||
|
#if defined(SHARED_LIBRARY_BUILD)
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
|
||||||
|
#if defined(SHAKA_IMPLEMENTATION)
|
||||||
|
#define SHAKA_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define SHAKA_EXPORT __declspec(dllimport)
|
||||||
|
#endif // defined(SHAKA_IMPLEMENTATION)
|
||||||
|
|
||||||
|
#else // defined(OS_WIN)
|
||||||
|
|
||||||
|
#if defined(SHAKA_IMPLEMENTATION)
|
||||||
|
#define SHAKA_EXPORT __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define SHAKA_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // defined(OS_WIN)
|
||||||
|
|
||||||
|
#else // defined(SHARED_LIBRARY_BUILD)
|
||||||
|
#define SHAKA_EXPORT
|
||||||
|
#endif // defined(SHARED_LIBRARY_BUILD)
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
|
||||||
/// MP4 (ISO-BMFF) output related parameters.
|
/// MP4 (ISO-BMFF) output related parameters.
|
||||||
|
@ -268,7 +291,7 @@ struct EncryptionParams {
|
||||||
/// @param stream_info Encrypted stream info.
|
/// @param stream_info Encrypted stream info.
|
||||||
/// @return the stream label associated with `stream_info`. Can be "AUDIO",
|
/// @return the stream label associated with `stream_info`. Can be "AUDIO",
|
||||||
/// "SD", "HD", "UHD1" or "UHD2".
|
/// "SD", "HD", "UHD1" or "UHD2".
|
||||||
static std::string DefaultStreamLabelFunction(
|
static SHAKA_EXPORT std::string DefaultStreamLabelFunction(
|
||||||
int max_sd_pixels,
|
int max_sd_pixels,
|
||||||
int max_hd_pixels,
|
int max_hd_pixels,
|
||||||
int max_uhd1_pixels,
|
int max_uhd1_pixels,
|
||||||
|
@ -321,6 +344,18 @@ struct DecryptionParams {
|
||||||
RawKeyDecryptionParams raw_key;
|
RawKeyDecryptionParams raw_key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Parameters used for testing.
|
||||||
|
struct TestParams {
|
||||||
|
/// Whether to dump input stream info.
|
||||||
|
bool dump_stream_info = false;
|
||||||
|
/// Inject a fake clock which always returns 0. This allows deterministic
|
||||||
|
/// output from packaging.
|
||||||
|
bool inject_fake_clock = false;
|
||||||
|
/// Inject and replace the library version string if specified, which is used
|
||||||
|
/// to populate the version string in the manifests / media files.
|
||||||
|
std::string injected_library_version;
|
||||||
|
};
|
||||||
|
|
||||||
/// Packaging parameters.
|
/// Packaging parameters.
|
||||||
struct PackagingParams {
|
struct PackagingParams {
|
||||||
/// Specify temporary directory for intermediate temporary files.
|
/// Specify temporary directory for intermediate temporary files.
|
||||||
|
@ -343,6 +378,9 @@ struct PackagingParams {
|
||||||
/// Encryption and Decryption Parameters.
|
/// Encryption and Decryption Parameters.
|
||||||
EncryptionParams encryption_params;
|
EncryptionParams encryption_params;
|
||||||
DecryptionParams decryption_params;
|
DecryptionParams decryption_params;
|
||||||
|
|
||||||
|
// Parameters for testing. Do not use in production.
|
||||||
|
TestParams test_params;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Defines a single input/output stream.
|
/// Defines a single input/output stream.
|
||||||
|
@ -394,7 +432,7 @@ struct StreamDescriptor {
|
||||||
std::string hls_playlist_name;
|
std::string hls_playlist_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShakaPackager {
|
class SHAKA_EXPORT ShakaPackager {
|
||||||
public:
|
public:
|
||||||
ShakaPackager();
|
ShakaPackager();
|
||||||
~ShakaPackager();
|
~ShakaPackager();
|
||||||
|
@ -415,6 +453,9 @@ class ShakaPackager {
|
||||||
/// Cancel packaging. Note that it has to be called from another thread.
|
/// Cancel packaging. Note that it has to be called from another thread.
|
||||||
void Cancel();
|
void Cancel();
|
||||||
|
|
||||||
|
/// @return The version of the library.
|
||||||
|
static std::string GetLibraryVersion();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ShakaPackager(const ShakaPackager&) = delete;
|
ShakaPackager(const ShakaPackager&) = delete;
|
||||||
ShakaPackager& operator=(const ShakaPackager&) = delete;
|
ShakaPackager& operator=(const ShakaPackager&) = delete;
|
||||||
|
|
|
@ -7,8 +7,8 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "packager/base/files/file_util.h"
|
#include "packager/base/files/file_util.h"
|
||||||
#include "packager/media/base/test/status_test_util.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/test/test_data_util.h"
|
#include "packager/base/path_service.h"
|
||||||
#include "packager/packager.h"
|
#include "packager/packager.h"
|
||||||
|
|
||||||
namespace shaka {
|
namespace shaka {
|
||||||
|
@ -26,6 +26,18 @@ const char kKeyIdHex[] = "e5007e6e9dcd5ac095202ed3758382cd";
|
||||||
const char kKeyHex[] = "6fc96fe628a265b13aeddec0bc421f4d";
|
const char kKeyHex[] = "6fc96fe628a265b13aeddec0bc421f4d";
|
||||||
const double kClearLeadInSeconds = 1.0;
|
const double kClearLeadInSeconds = 1.0;
|
||||||
|
|
||||||
|
std::string GetTestDataFilePath(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("media"))
|
||||||
|
.Append(FILE_PATH_LITERAL("test"))
|
||||||
|
.Append(FILE_PATH_LITERAL("data"))
|
||||||
|
.AppendASCII(name);
|
||||||
|
return file_path.AsUTF8Unsafe();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class PackagerTest : public ::testing::Test {
|
class PackagerTest : public ::testing::Test {
|
||||||
|
@ -64,14 +76,12 @@ class PackagerTest : public ::testing::Test {
|
||||||
std::vector<StreamDescriptor> stream_descriptors;
|
std::vector<StreamDescriptor> stream_descriptors;
|
||||||
StreamDescriptor stream_descriptor;
|
StreamDescriptor stream_descriptor;
|
||||||
|
|
||||||
stream_descriptor.input =
|
stream_descriptor.input = GetTestDataFilePath(kTestFile);
|
||||||
media::GetTestDataFilePath(kTestFile).AsUTF8Unsafe();
|
|
||||||
stream_descriptor.stream_selector = "video";
|
stream_descriptor.stream_selector = "video";
|
||||||
stream_descriptor.output = GetFullPath(kOutputVideo);
|
stream_descriptor.output = GetFullPath(kOutputVideo);
|
||||||
stream_descriptors.push_back(stream_descriptor);
|
stream_descriptors.push_back(stream_descriptor);
|
||||||
|
|
||||||
stream_descriptor.input =
|
stream_descriptor.input = GetTestDataFilePath(kTestFile);
|
||||||
media::GetTestDataFilePath(kTestFile).AsUTF8Unsafe();
|
|
||||||
stream_descriptor.stream_selector = "audio";
|
stream_descriptor.stream_selector = "audio";
|
||||||
stream_descriptor.output = GetFullPath(kOutputAudio);
|
stream_descriptor.output = GetFullPath(kOutputAudio);
|
||||||
stream_descriptors.push_back(stream_descriptor);
|
stream_descriptors.push_back(stream_descriptor);
|
||||||
|
@ -83,11 +93,16 @@ class PackagerTest : public ::testing::Test {
|
||||||
base::FilePath test_directory_;
|
base::FilePath test_directory_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TEST_F(PackagerTest, Version) {
|
||||||
|
EXPECT_FALSE(ShakaPackager::GetLibraryVersion().empty());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(PackagerTest, Success) {
|
TEST_F(PackagerTest, Success) {
|
||||||
ShakaPackager packager;
|
ShakaPackager packager;
|
||||||
ASSERT_OK(
|
ASSERT_TRUE(
|
||||||
packager.Initialize(SetupPackagingParams(), SetupStreamDescriptors()));
|
packager.Initialize(SetupPackagingParams(), SetupStreamDescriptors())
|
||||||
ASSERT_OK(packager.Run());
|
.ok());
|
||||||
|
ASSERT_TRUE(packager.Run().ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PackagerTest, MissingStreamDescriptors) {
|
TEST_F(PackagerTest, MissingStreamDescriptors) {
|
||||||
|
@ -101,15 +116,13 @@ TEST_F(PackagerTest, MixingSegmentTemplateAndSingleSegment) {
|
||||||
std::vector<StreamDescriptor> stream_descriptors;
|
std::vector<StreamDescriptor> stream_descriptors;
|
||||||
StreamDescriptor stream_descriptor;
|
StreamDescriptor stream_descriptor;
|
||||||
|
|
||||||
stream_descriptor.input =
|
stream_descriptor.input = GetTestDataFilePath(kTestFile);
|
||||||
media::GetTestDataFilePath(kTestFile).AsUTF8Unsafe();
|
|
||||||
stream_descriptor.stream_selector = "video";
|
stream_descriptor.stream_selector = "video";
|
||||||
stream_descriptor.output = GetFullPath(kOutputVideo);
|
stream_descriptor.output = GetFullPath(kOutputVideo);
|
||||||
stream_descriptor.segment_template = GetFullPath(kOutputVideoTemplate);
|
stream_descriptor.segment_template = GetFullPath(kOutputVideoTemplate);
|
||||||
stream_descriptors.push_back(stream_descriptor);
|
stream_descriptors.push_back(stream_descriptor);
|
||||||
|
|
||||||
stream_descriptor.input =
|
stream_descriptor.input = GetTestDataFilePath(kTestFile);
|
||||||
media::GetTestDataFilePath(kTestFile).AsUTF8Unsafe();
|
|
||||||
stream_descriptor.stream_selector = "audio";
|
stream_descriptor.stream_selector = "audio";
|
||||||
stream_descriptor.output = GetFullPath(kOutputAudio);
|
stream_descriptor.output = GetFullPath(kOutputAudio);
|
||||||
stream_descriptor.segment_template.clear();
|
stream_descriptor.segment_template.clear();
|
||||||
|
@ -125,8 +138,9 @@ TEST_F(PackagerTest, SegmentAlignedAndSubsegmentNotAligned) {
|
||||||
packaging_params.chunking_params.segment_sap_aligned = true;
|
packaging_params.chunking_params.segment_sap_aligned = true;
|
||||||
packaging_params.chunking_params.subsegment_sap_aligned = false;
|
packaging_params.chunking_params.subsegment_sap_aligned = false;
|
||||||
ShakaPackager packager;
|
ShakaPackager packager;
|
||||||
ASSERT_OK(packager.Initialize(packaging_params, SetupStreamDescriptors()));
|
ASSERT_TRUE(
|
||||||
ASSERT_OK(packager.Run());
|
packager.Initialize(packaging_params, SetupStreamDescriptors()).ok());
|
||||||
|
ASSERT_TRUE(packager.Run().ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PackagerTest, SegmentNotAlignedButSubsegmentAligned) {
|
TEST_F(PackagerTest, SegmentNotAlignedButSubsegmentAligned) {
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
# Copyright (c) 2012 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.
|
||||||
|
|
||||||
|
# This file is meant to be included into a target to provide a rule
|
||||||
|
# to invoke protoc in a consistent manner. For Java-targets, see
|
||||||
|
# protoc_java.gypi.
|
||||||
|
#
|
||||||
|
# To use this, create a gyp target with the following form:
|
||||||
|
# {
|
||||||
|
# 'target_name': 'my_proto_lib',
|
||||||
|
# 'type': 'static_library',
|
||||||
|
# 'sources': [
|
||||||
|
# 'foo.proto',
|
||||||
|
# 'bar.proto',
|
||||||
|
# ],
|
||||||
|
# 'variables': {
|
||||||
|
# # Optional, see below: 'proto_in_dir': '.'
|
||||||
|
# 'proto_out_dir': 'dir/for/my_proto_lib'
|
||||||
|
# },
|
||||||
|
# 'includes': ['path/to/this/gypi/file'],
|
||||||
|
# }
|
||||||
|
# If necessary, you may add normal .cc files to the sources list or other gyp
|
||||||
|
# dependencies. The proto headers are guaranteed to be generated before any
|
||||||
|
# source files, even within this target, are compiled.
|
||||||
|
#
|
||||||
|
# The 'proto_in_dir' variable must be the relative path to the
|
||||||
|
# directory containing the .proto files. If left out, it defaults to '.'.
|
||||||
|
#
|
||||||
|
# The 'proto_out_dir' variable specifies the path suffix that output
|
||||||
|
# files are generated under. Targets that gyp-depend on my_proto_lib
|
||||||
|
# will be able to include the resulting proto headers with an include
|
||||||
|
# like:
|
||||||
|
# #include "dir/for/my_proto_lib/foo.pb.h"
|
||||||
|
#
|
||||||
|
# If you need to add an EXPORT macro to a protobuf's c++ header, set the
|
||||||
|
# 'cc_generator_options' variable with the value: 'dllexport_decl=FOO_EXPORT:'
|
||||||
|
# e.g. 'dllexport_decl=BASE_EXPORT:'
|
||||||
|
#
|
||||||
|
# It is likely you also need to #include a file for the above EXPORT macro to
|
||||||
|
# work. You can do so with the 'cc_include' variable.
|
||||||
|
# e.g. 'base/base_export.h'
|
||||||
|
#
|
||||||
|
# Implementation notes:
|
||||||
|
# A proto_out_dir of foo/bar produces
|
||||||
|
# <(SHARED_INTERMEDIATE_DIR)/protoc_out/foo/bar/{file1,file2}.pb.{cc,h}
|
||||||
|
# <(SHARED_INTERMEDIATE_DIR)/pyproto/foo/bar/{file1,file2}_pb2.py
|
||||||
|
|
||||||
|
{
|
||||||
|
'variables': {
|
||||||
|
'protoc_wrapper': '<(DEPTH)/tools/protoc_wrapper/protoc_wrapper.py',
|
||||||
|
'cc_dir': '<(SHARED_INTERMEDIATE_DIR)/protoc_out/<(proto_out_dir)',
|
||||||
|
'py_dir': '<(PRODUCT_DIR)/pyproto/<(proto_out_dir)',
|
||||||
|
'cc_generator_options%': '',
|
||||||
|
'generate_python%': 1,
|
||||||
|
'generate_cc%': 1,
|
||||||
|
# Name of plugin executable which generates custom cc stubs.
|
||||||
|
# If passed, generator_plugin_suffix (before .cc and .h) is also required.
|
||||||
|
'generator_plugin%': '',
|
||||||
|
'generator_plugin_options%': '',
|
||||||
|
'cc_include%': '',
|
||||||
|
'proto_in_dir%': '.',
|
||||||
|
'conditions': [
|
||||||
|
['use_system_protobuf==0', {
|
||||||
|
'protoc': '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
|
||||||
|
}, { # use_system_protobuf==1
|
||||||
|
'protoc': '<!(which protoc)',
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'rules': [
|
||||||
|
{
|
||||||
|
'rule_name': 'genproto',
|
||||||
|
'extension': 'proto',
|
||||||
|
'inputs': [
|
||||||
|
'<(protoc_wrapper)',
|
||||||
|
'<(protoc)',
|
||||||
|
],
|
||||||
|
'action': [
|
||||||
|
'python',
|
||||||
|
'<(protoc_wrapper)',
|
||||||
|
# If no cc_include specified --protobuf option will be ignored.
|
||||||
|
'--include',
|
||||||
|
'<(cc_include)',
|
||||||
|
'--protobuf',
|
||||||
|
'<(cc_dir)/<(RULE_INPUT_ROOT).pb.h',
|
||||||
|
# Using the --arg val form (instead of --arg=val) allows gyp's msvs rule
|
||||||
|
# generation to correct 'val' which is a path.
|
||||||
|
'--proto-in-dir','<(proto_in_dir)',
|
||||||
|
# Naively you'd use <(RULE_INPUT_PATH) here, but protoc requires
|
||||||
|
# --proto_path is a strict prefix of the path given as an argument.
|
||||||
|
'--proto-in-file','<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)',
|
||||||
|
'--use-system-protobuf=<(use_system_protobuf)',
|
||||||
|
'--',
|
||||||
|
'<(protoc)',
|
||||||
|
],
|
||||||
|
'message': 'Generating C++ and Python code from <(RULE_INPUT_PATH)',
|
||||||
|
'process_outputs_as_sources': 1,
|
||||||
|
|
||||||
|
'conditions': [
|
||||||
|
['generate_python==1', {
|
||||||
|
'outputs': [
|
||||||
|
'<(py_dir)/<(RULE_INPUT_ROOT)_pb2.py',
|
||||||
|
],
|
||||||
|
'action': [
|
||||||
|
'--python_out',
|
||||||
|
'<(py_dir)',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
['generate_cc==1', {
|
||||||
|
'outputs': [
|
||||||
|
'<(cc_dir)/<(RULE_INPUT_ROOT).pb.cc',
|
||||||
|
'<(cc_dir)/<(RULE_INPUT_ROOT).pb.h',
|
||||||
|
],
|
||||||
|
'action': [
|
||||||
|
'--cpp_out',
|
||||||
|
'<(cc_generator_options)<(cc_dir)',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
['generator_plugin!=""', {
|
||||||
|
'outputs': [
|
||||||
|
'<(cc_dir)/<(RULE_INPUT_ROOT)<(generator_plugin_suffix).cc',
|
||||||
|
'<(cc_dir)/<(RULE_INPUT_ROOT)<(generator_plugin_suffix).h',
|
||||||
|
],
|
||||||
|
'action': [
|
||||||
|
'--plugin',
|
||||||
|
'protoc-gen-plugin=<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)<(generator_plugin)<(EXECUTABLE_SUFFIX)',
|
||||||
|
'--plugin_out',
|
||||||
|
'<(generator_plugin_options)<(cc_dir)',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'<(DEPTH)/third_party/protobuf/protobuf.gyp:protoc#host',
|
||||||
|
],
|
||||||
|
'include_dirs': [
|
||||||
|
'<(SHARED_INTERMEDIATE_DIR)/protoc_out',
|
||||||
|
'<(DEPTH)',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': [
|
||||||
|
'<(SHARED_INTERMEDIATE_DIR)/protoc_out',
|
||||||
|
'<(DEPTH)',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
# This target exports a hard dependency because it generates header files.
|
||||||
|
'hard_dependency': 1,
|
||||||
|
|
||||||
|
# If using built-in cc generator the resulting headers reference headers
|
||||||
|
# within protobuf_lite, hence dependencies require those headers too.
|
||||||
|
# In case of generator plugin such issues should be resolved by invoker.
|
||||||
|
'conditions': [
|
||||||
|
['generate_cc==1', {
|
||||||
|
'dependencies': [
|
||||||
|
# Use 'protobuf_full_do_not_use' to allow generating non-LITE (full)
|
||||||
|
# protobuf. We need full protobuf to serialize and deserialize human
|
||||||
|
# readable protobuf messages.
|
||||||
|
'<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_full_do_not_use',
|
||||||
|
],
|
||||||
|
'export_dependent_settings': [
|
||||||
|
'<(DEPTH)/third_party/protobuf/protobuf.gyp:protobuf_full_do_not_use',
|
||||||
|
],
|
||||||
|
}],
|
||||||
|
],
|
||||||
|
}
|
|
@ -6,8 +6,9 @@
|
||||||
|
|
||||||
#include "packager/version/version.h"
|
#include "packager/version/version.h"
|
||||||
|
|
||||||
#include "packager/base/lazy_instance.h"
|
#include "packager/base/synchronization/read_write_lock.h"
|
||||||
|
|
||||||
|
namespace shaka {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#if defined(PACKAGER_VERSION)
|
#if defined(PACKAGER_VERSION)
|
||||||
|
@ -29,29 +30,37 @@ class Version {
|
||||||
Version() : version_(kPackagerVersion) {}
|
Version() : version_(kPackagerVersion) {}
|
||||||
~Version() {}
|
~Version() {}
|
||||||
|
|
||||||
const std::string& version() { return version_; }
|
const std::string& GetVersion() {
|
||||||
void set_version(const std::string& version) { version_ = version; }
|
base::subtle::AutoReadLock read_lock(lock_);
|
||||||
|
return version_;
|
||||||
|
}
|
||||||
|
void SetVersion(const std::string& version) {
|
||||||
|
base::subtle::AutoWriteLock write_lock(lock_);
|
||||||
|
version_ = version;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Version(const Version&) = delete;
|
||||||
|
Version& operator=(const Version&) = delete;
|
||||||
|
|
||||||
|
base::subtle::ReadWriteLock lock_;
|
||||||
std::string version_;
|
std::string version_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace shaka {
|
static Version g_packager_version;
|
||||||
|
|
||||||
base::LazyInstance<Version> g_packager_version;
|
|
||||||
|
|
||||||
std::string GetPackagerProjectUrl(){
|
std::string GetPackagerProjectUrl(){
|
||||||
return kPackagerGithubUrl;
|
return kPackagerGithubUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetPackagerVersion() {
|
std::string GetPackagerVersion() {
|
||||||
return g_packager_version.Get().version();
|
return g_packager_version.GetVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPackagerVersionForTesting(const std::string& version) {
|
void SetPackagerVersionForTesting(const std::string& version) {
|
||||||
g_packager_version.Get().set_version(version);
|
g_packager_version.SetVersion(version);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace shaka
|
} // namespace shaka
|
||||||
|
|
Loading…
Reference in New Issue