feat: port demuxer and app to cmake (#1260)
Related to issue #1047 After this it should be possible to build a working `packager` application from the `cmake` branch. Some further logging improvements may be needed to get full parity with the `main` branch in terms of ability to do verbose debug logging, but other than that everything is expected to work.
This commit is contained in:
parent
274c885253
commit
6b68c138cc
|
@ -9,6 +9,7 @@
|
|||
# Build static libs by default, or shared if LIBPACKAGER_SHARED is defined.
|
||||
if(LIBPACKAGER_SHARED)
|
||||
add_definitions(-DSHARED_LIBRARY_BUILD)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
# Global C++ flags.
|
||||
|
@ -64,4 +65,113 @@ add_subdirectory(third_party)
|
|||
add_subdirectory(tools)
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(version)
|
||||
add_subdirectory(app)
|
||||
|
||||
set(libpackager_sources
|
||||
app/job_manager.cc
|
||||
app/job_manager.h
|
||||
app/muxer_factory.cc
|
||||
app/muxer_factory.h
|
||||
app/packager_util.cc
|
||||
app/packager_util.h
|
||||
app/single_thread_job_manager.cc
|
||||
app/single_thread_job_manager.h
|
||||
packager.cc
|
||||
packager.h
|
||||
)
|
||||
|
||||
if(LIBPACKAGER_SHARED)
|
||||
add_library(libpackager SHARED ${libpackager_sources})
|
||||
target_compile_definitions(libpackager PUBLIC SHAKA_IMPLEMENTATION)
|
||||
else()
|
||||
add_library(libpackager STATIC ${libpackager_sources})
|
||||
endif()
|
||||
|
||||
target_link_libraries(libpackager
|
||||
file
|
||||
hls_builder
|
||||
media_chunking
|
||||
media_codecs
|
||||
media_crypto
|
||||
demuxer
|
||||
media_event
|
||||
dvb
|
||||
mp2t
|
||||
mp4
|
||||
packed_audio
|
||||
ttml
|
||||
formats_webm
|
||||
wvm
|
||||
media_replicator
|
||||
media_trick_play
|
||||
mpd_builder
|
||||
mbedtls
|
||||
string_utils
|
||||
version
|
||||
)
|
||||
|
||||
add_executable(packager
|
||||
app/ad_cue_generator_flags.cc
|
||||
app/ad_cue_generator_flags.h
|
||||
app/crypto_flags.cc
|
||||
app/crypto_flags.h
|
||||
app/hls_flags.cc
|
||||
app/hls_flags.h
|
||||
app/manifest_flags.cc
|
||||
app/manifest_flags.h
|
||||
app/mpd_flags.cc
|
||||
app/mpd_flags.h
|
||||
app/muxer_flags.cc
|
||||
app/muxer_flags.h
|
||||
app/packager_main.cc
|
||||
app/playready_key_encryption_flags.cc
|
||||
app/playready_key_encryption_flags.h
|
||||
app/raw_key_encryption_flags.cc
|
||||
app/raw_key_encryption_flags.h
|
||||
app/protection_system_flags.cc
|
||||
app/protection_system_flags.h
|
||||
app/retired_flags.cc
|
||||
app/retired_flags.h
|
||||
app/stream_descriptor.cc
|
||||
app/stream_descriptor.h
|
||||
app/validate_flag.cc
|
||||
app/validate_flag.h
|
||||
app/vlog_flags.cc
|
||||
app/vlog_flags.h
|
||||
app/widevine_encryption_flags.cc
|
||||
app/widevine_encryption_flags.h
|
||||
)
|
||||
target_link_libraries(packager
|
||||
libpackager
|
||||
hex_bytes_flags
|
||||
absl::flags
|
||||
absl::flags_parse
|
||||
license_notice
|
||||
glog
|
||||
absl::strings
|
||||
string_utils
|
||||
)
|
||||
|
||||
add_executable(mpd_generator
|
||||
app/mpd_generator.cc
|
||||
app/mpd_generator_flags.h
|
||||
app/vlog_flags.cc
|
||||
app/vlog_flags.h
|
||||
)
|
||||
target_link_libraries(mpd_generator
|
||||
mpd_builder
|
||||
mpd_util
|
||||
absl::flags
|
||||
absl::flags_parse
|
||||
absl::strings
|
||||
glog
|
||||
license_notice
|
||||
)
|
||||
|
||||
add_executable(packager_test
|
||||
packager_test.cc
|
||||
)
|
||||
target_link_libraries(packager_test
|
||||
libpackager
|
||||
gmock
|
||||
gtest
|
||||
gtest_main)
|
||||
|
|
|
@ -8,12 +8,13 @@
|
|||
|
||||
#include "packager/app/ad_cue_generator_flags.h"
|
||||
|
||||
DEFINE_string(ad_cues,
|
||||
"",
|
||||
"List of cuepoint markers."
|
||||
"This flag accepts semicolon separated pairs and components in "
|
||||
"the pair are separated by a comma and the second component "
|
||||
"duration is optional. For example --ad_cues "
|
||||
"{start_time}[,{duration}][;{start_time}[,{duration}]]..."
|
||||
"The start_time represents the start of the cue marker in "
|
||||
"seconds relative to the start of the program.");
|
||||
ABSL_FLAG(std::string,
|
||||
ad_cues,
|
||||
"",
|
||||
"List of cuepoint markers."
|
||||
"This flag accepts semicolon separated pairs and components in "
|
||||
"the pair are separated by a comma and the second component "
|
||||
"duration is optional. For example --ad_cues "
|
||||
"{start_time}[,{duration}][;{start_time}[,{duration}]]..."
|
||||
"The start_time represents the start of the cue marker in "
|
||||
"seconds relative to the start of the program.");
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
#ifndef PACKAGER_APP_AD_CUE_GENERATOR_FLAGS_H_
|
||||
#define PACKAGER_APP_AD_CUE_GENERATOR_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_string(ad_cues);
|
||||
ABSL_DECLARE_FLAG(std::string, ad_cues);
|
||||
|
||||
#endif // PACKAGER_APP_AD_CUE_GENERATOR_FLAGS_H_
|
||||
|
|
|
@ -5,14 +5,17 @@
|
|||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "packager/app/crypto_flags.h"
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
DEFINE_string(protection_scheme,
|
||||
"cenc",
|
||||
"Specify a protection scheme, 'cenc' or 'cbc1' or pattern-based "
|
||||
"protection schemes 'cens' or 'cbcs'.");
|
||||
DEFINE_int32(
|
||||
ABSL_FLAG(std::string,
|
||||
protection_scheme,
|
||||
"cenc",
|
||||
"Specify a protection scheme, 'cenc' or 'cbc1' or pattern-based "
|
||||
"protection schemes 'cens' or 'cbcs'.");
|
||||
ABSL_FLAG(
|
||||
int32_t,
|
||||
crypt_byte_block,
|
||||
1,
|
||||
"Specify the count of the encrypted blocks in the protection pattern, "
|
||||
|
@ -20,16 +23,21 @@ DEFINE_int32(
|
|||
"patterns (crypt_byte_block:skip_byte_block): 1:9 (default), 5:5, 10:0. "
|
||||
"Apply to video streams with 'cbcs' and 'cens' protection schemes only; "
|
||||
"ignored otherwise.");
|
||||
DEFINE_int32(
|
||||
ABSL_FLAG(
|
||||
int32_t,
|
||||
skip_byte_block,
|
||||
9,
|
||||
"Specify the count of the unencrypted blocks in the protection pattern. "
|
||||
"Apply to video streams with 'cbcs' and 'cens' protection schemes only; "
|
||||
"ignored otherwise.");
|
||||
DEFINE_bool(vp9_subsample_encryption, true, "Enable VP9 subsample encryption.");
|
||||
DEFINE_string(playready_extra_header_data,
|
||||
"",
|
||||
"Extra XML data to add to PlayReady headers.");
|
||||
ABSL_FLAG(bool,
|
||||
vp9_subsample_encryption,
|
||||
true,
|
||||
"Enable VP9 subsample encryption.");
|
||||
ABSL_FLAG(std::string,
|
||||
playready_extra_header_data,
|
||||
"",
|
||||
"Extra XML data to add to PlayReady headers.");
|
||||
|
||||
bool ValueNotGreaterThanTen(const char* flagname, int32_t value) {
|
||||
if (value > 10) {
|
||||
|
@ -54,6 +62,26 @@ bool ValueIsXml(const char* flagname, const std::string& value) {
|
|||
return true;
|
||||
}
|
||||
|
||||
DEFINE_validator(crypt_byte_block, &ValueNotGreaterThanTen);
|
||||
DEFINE_validator(skip_byte_block, &ValueNotGreaterThanTen);
|
||||
DEFINE_validator(playready_extra_header_data, &ValueIsXml);
|
||||
namespace shaka {
|
||||
bool ValidateCryptoFlags() {
|
||||
bool success = true;
|
||||
|
||||
auto crypt_byte_block = absl::GetFlag(FLAGS_crypt_byte_block);
|
||||
if (!ValueNotGreaterThanTen("crypt_byte_block", crypt_byte_block)) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
auto skip_byte_block = absl::GetFlag(FLAGS_skip_byte_block);
|
||||
if (!ValueNotGreaterThanTen("skip_byte_block", skip_byte_block)) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
auto playready_extra_header_data =
|
||||
absl::GetFlag(FLAGS_playready_extra_header_data);
|
||||
if (!ValueIsXml("playready_extra_header_data", playready_extra_header_data)) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
} // namespace shaka
|
||||
|
|
|
@ -10,12 +10,17 @@
|
|||
#ifndef PACKAGER_APP_CRYPTO_FLAGS_H_
|
||||
#define PACKAGER_APP_CRYPTO_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_string(protection_scheme);
|
||||
DECLARE_int32(crypt_byte_block);
|
||||
DECLARE_int32(skip_byte_block);
|
||||
DECLARE_bool(vp9_subsample_encryption);
|
||||
DECLARE_string(playready_extra_header_data);
|
||||
ABSL_DECLARE_FLAG(std::string, protection_scheme);
|
||||
ABSL_DECLARE_FLAG(int32_t, crypt_byte_block);
|
||||
ABSL_DECLARE_FLAG(int32_t, skip_byte_block);
|
||||
ABSL_DECLARE_FLAG(bool, vp9_subsample_encryption);
|
||||
ABSL_DECLARE_FLAG(std::string, playready_extra_header_data);
|
||||
|
||||
namespace shaka {
|
||||
bool ValidateCryptoFlags();
|
||||
}
|
||||
|
||||
#endif // PACKAGER_APP_CRYPTO_FLAGS_H_
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright 2017 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "packager/app/gflags_hex_bytes.h"
|
||||
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
|
||||
namespace shaka {
|
||||
|
||||
bool ValidateHexString(const char* flagname,
|
||||
const std::string& value,
|
||||
std::vector<uint8_t>* value_bytes) {
|
||||
std::vector<uint8_t> temp_value_bytes;
|
||||
if (!value.empty() && !base::HexStringToBytes(value, &temp_value_bytes)) {
|
||||
printf("Invalid hex string for --%s: %s\n", flagname, value.c_str());
|
||||
return false;
|
||||
}
|
||||
value_bytes->swap(temp_value_bytes);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace shaka
|
|
@ -1,50 +0,0 @@
|
|||
// Copyright 2017 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
//
|
||||
// Extends gflags to support hex formatted bytes.
|
||||
|
||||
#ifndef PACKAGER_APP_GFLAGS_HEX_BYTES_H_
|
||||
#define PACKAGER_APP_GFLAGS_HEX_BYTES_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace shaka {
|
||||
bool ValidateHexString(const char* flagname,
|
||||
const std::string& value,
|
||||
std::vector<uint8_t>* value_bytes);
|
||||
} // namespace shaka
|
||||
|
||||
// The raw bytes will be available in FLAGS_##name##_bytes.
|
||||
// The original gflag variable FLAGS_##name is defined in shaka_gflags_extension
|
||||
// and not exposed directly.
|
||||
#define DECLARE_hex_bytes(name) \
|
||||
namespace shaka_gflags_extension { \
|
||||
DECLARE_string(name); \
|
||||
} \
|
||||
namespace shaka_gflags_extension { \
|
||||
extern std::vector<uint8_t> FLAGS_##name##_bytes; \
|
||||
} \
|
||||
using shaka_gflags_extension::FLAGS_##name##_bytes
|
||||
|
||||
#define DEFINE_hex_bytes(name, val, txt) \
|
||||
namespace shaka_gflags_extension { \
|
||||
DEFINE_string(name, val, txt); \
|
||||
} \
|
||||
namespace shaka_gflags_extension { \
|
||||
std::vector<uint8_t> FLAGS_##name##_bytes; \
|
||||
static bool hex_validator_##name = gflags::RegisterFlagValidator( \
|
||||
&FLAGS_##name, \
|
||||
[](const char* flagname, const std::string& value) { \
|
||||
return shaka::ValidateHexString(flagname, value, \
|
||||
&FLAGS_##name##_bytes); \
|
||||
}); \
|
||||
} \
|
||||
using shaka_gflags_extension::FLAGS_##name##_bytes
|
||||
|
||||
#endif // PACKAGER_APP_GFLAGS_HEX_BYTES_H_
|
|
@ -6,27 +6,32 @@
|
|||
|
||||
#include "packager/app/hls_flags.h"
|
||||
|
||||
DEFINE_string(hls_master_playlist_output,
|
||||
"",
|
||||
"Output path for the master playlist for HLS. This flag must be"
|
||||
"used to output HLS.");
|
||||
DEFINE_string(hls_base_url,
|
||||
"",
|
||||
"The base URL for the Media Playlists and media files listed in "
|
||||
"the playlists. This is the prefix for the files.");
|
||||
DEFINE_string(hls_key_uri,
|
||||
"",
|
||||
"The key uri for 'identity' and 'com.apple.streamingkeydelivery' "
|
||||
"key formats. Ignored if the playlist is not encrypted or not "
|
||||
"using the above key formats.");
|
||||
DEFINE_string(hls_playlist_type,
|
||||
"VOD",
|
||||
"VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in "
|
||||
"the HLS specification. For hls_playlist_type of LIVE, "
|
||||
"EXT-X-PLAYLIST-TYPE tag is omitted.");
|
||||
DEFINE_int32(hls_media_sequence_number,
|
||||
0,
|
||||
"Number. This HLS-only parameter defines the initial "
|
||||
"EXT-X-MEDIA-SEQUENCE value, which allows continuous media "
|
||||
"sequence across packager restarts. See #691 for more "
|
||||
"information about the reasoning of this and its use cases.");
|
||||
ABSL_FLAG(std::string,
|
||||
hls_master_playlist_output,
|
||||
"",
|
||||
"Output path for the master playlist for HLS. This flag must be"
|
||||
"used to output HLS.");
|
||||
ABSL_FLAG(std::string,
|
||||
hls_base_url,
|
||||
"",
|
||||
"The base URL for the Media Playlists and media files listed in "
|
||||
"the playlists. This is the prefix for the files.");
|
||||
ABSL_FLAG(std::string,
|
||||
hls_key_uri,
|
||||
"",
|
||||
"The key uri for 'identity' and 'com.apple.streamingkeydelivery' "
|
||||
"key formats. Ignored if the playlist is not encrypted or not "
|
||||
"using the above key formats.");
|
||||
ABSL_FLAG(std::string,
|
||||
hls_playlist_type,
|
||||
"VOD",
|
||||
"VOD, EVENT, or LIVE. This defines the EXT-X-PLAYLIST-TYPE in "
|
||||
"the HLS specification. For hls_playlist_type of LIVE, "
|
||||
"EXT-X-PLAYLIST-TYPE tag is omitted.");
|
||||
ABSL_FLAG(int32_t,
|
||||
hls_media_sequence_number,
|
||||
0,
|
||||
"Number. This HLS-only parameter defines the initial "
|
||||
"EXT-X-MEDIA-SEQUENCE value, which allows continuous media "
|
||||
"sequence across packager restarts. See #691 for more "
|
||||
"information about the reasoning of this and its use cases.");
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
#ifndef PACKAGER_APP_HLS_FLAGS_H_
|
||||
#define PACKAGER_APP_HLS_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_string(hls_master_playlist_output);
|
||||
DECLARE_string(hls_base_url);
|
||||
DECLARE_string(hls_key_uri);
|
||||
DECLARE_string(hls_playlist_type);
|
||||
DECLARE_int32(hls_media_sequence_number);
|
||||
ABSL_DECLARE_FLAG(std::string, hls_master_playlist_output);
|
||||
ABSL_DECLARE_FLAG(std::string, hls_base_url);
|
||||
ABSL_DECLARE_FLAG(std::string, hls_key_uri);
|
||||
ABSL_DECLARE_FLAG(std::string, hls_playlist_type);
|
||||
ABSL_DECLARE_FLAG(int32_t, hls_media_sequence_number);
|
||||
|
||||
#endif // PACKAGER_APP_HLS_FLAGS_H_
|
||||
|
|
|
@ -47,8 +47,10 @@ const Status& Job::Run() {
|
|||
}
|
||||
|
||||
void Job::Join() {
|
||||
if (thread_)
|
||||
if (thread_) {
|
||||
thread_->join();
|
||||
thread_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JobManager::JobManager(std::unique_ptr<SyncPointQueue> sync_points)
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
// Copyright 2014 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "packager/app/libcrypto_threading.h"
|
||||
|
||||
#include <openssl/thread.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/synchronization/lock.h"
|
||||
#include "packager/base/threading/platform_thread.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<base::Lock[]> global_locks;
|
||||
|
||||
void LockFunction(int mode, int n, const char* file, int line) {
|
||||
VLOG(2) << "CryptoLock @ " << file << ":" << line;
|
||||
if (mode & CRYPTO_LOCK)
|
||||
global_locks[n].Acquire();
|
||||
else
|
||||
global_locks[n].Release();
|
||||
}
|
||||
|
||||
void ThreadIdFunction(CRYPTO_THREADID* id) {
|
||||
CRYPTO_THREADID_set_numeric(
|
||||
id, static_cast<unsigned long>(base::PlatformThread::CurrentId()));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
LibcryptoThreading::LibcryptoThreading() {
|
||||
global_locks.reset(new base::Lock[CRYPTO_num_locks()]);
|
||||
CRYPTO_THREADID_set_callback(ThreadIdFunction);
|
||||
CRYPTO_set_locking_callback(LockFunction);
|
||||
}
|
||||
|
||||
LibcryptoThreading::~LibcryptoThreading() {
|
||||
CRYPTO_THREADID_set_callback(NULL);
|
||||
CRYPTO_set_locking_callback(NULL);
|
||||
global_locks.reset();
|
||||
}
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright 2014 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef APP_LIBCRYPTO_THREADING_H_
|
||||
#define APP_LIBCRYPTO_THREADING_H_
|
||||
|
||||
#include "packager/base/macros.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
|
||||
/// Convenience class which initializes and terminates libcrypto threading.
|
||||
class LibcryptoThreading {
|
||||
public:
|
||||
LibcryptoThreading();
|
||||
~LibcryptoThreading();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LibcryptoThreading);
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
} // namespace shaka
|
||||
|
||||
#endif // APP_LIBCRYPTO_THREADING_H_
|
|
@ -6,11 +6,13 @@
|
|||
|
||||
#include "packager/app/manifest_flags.h"
|
||||
|
||||
DEFINE_double(time_shift_buffer_depth,
|
||||
1800.0,
|
||||
"Guaranteed duration of the time shifting buffer for HLS LIVE "
|
||||
"playlists and DASH dynamic media presentations, in seconds.");
|
||||
DEFINE_uint64(
|
||||
ABSL_FLAG(double,
|
||||
time_shift_buffer_depth,
|
||||
1800.0,
|
||||
"Guaranteed duration of the time shifting buffer for HLS LIVE "
|
||||
"playlists and DASH dynamic media presentations, in seconds.");
|
||||
ABSL_FLAG(
|
||||
uint64_t,
|
||||
preserved_segments_outside_live_window,
|
||||
50,
|
||||
"Segments outside the live window (defined by '--time_shift_buffer_depth') "
|
||||
|
@ -19,17 +21,19 @@ DEFINE_uint64(
|
|||
"stages of content serving pipeline, so that the segments stay accessible "
|
||||
"as they may still be accessed by the player."
|
||||
"The segments are not removed if the value is zero.");
|
||||
DEFINE_string(default_language,
|
||||
"",
|
||||
"For DASH, any audio/text tracks tagged with this language will "
|
||||
"have <Role ... value=\"main\" /> in the manifest; For HLS, the "
|
||||
"first audio/text rendition in a group tagged with this language "
|
||||
"will have 'DEFAULT' attribute set to 'YES'. This allows the "
|
||||
"player to choose the correct default language for the content."
|
||||
"This applies to both audio and text tracks. The default "
|
||||
"language for text tracks can be overriden by "
|
||||
"'--default_text_language'.");
|
||||
DEFINE_string(default_text_language,
|
||||
"",
|
||||
"Same as above, but this applies to text tracks only, and "
|
||||
"overrides the default language for text tracks.");
|
||||
ABSL_FLAG(std::string,
|
||||
default_language,
|
||||
"",
|
||||
"For DASH, any audio/text tracks tagged with this language will "
|
||||
"have <Role ... value=\"main\" /> in the manifest; For HLS, the "
|
||||
"first audio/text rendition in a group tagged with this language "
|
||||
"will have 'DEFAULT' attribute set to 'YES'. This allows the "
|
||||
"player to choose the correct default language for the content."
|
||||
"This applies to both audio and text tracks. The default "
|
||||
"language for text tracks can be overriden by "
|
||||
"'--default_text_language'.");
|
||||
ABSL_FLAG(std::string,
|
||||
default_text_language,
|
||||
"",
|
||||
"Same as above, but this applies to text tracks only, and "
|
||||
"overrides the default language for text tracks.");
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
#ifndef PACKAGER_APP_MANIFEST_FLAGS_H_
|
||||
#define PACKAGER_APP_MANIFEST_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_double(time_shift_buffer_depth);
|
||||
DECLARE_uint64(preserved_segments_outside_live_window);
|
||||
DECLARE_string(default_language);
|
||||
DECLARE_string(default_text_language);
|
||||
ABSL_DECLARE_FLAG(double, time_shift_buffer_depth);
|
||||
ABSL_DECLARE_FLAG(uint64_t, preserved_segments_outside_live_window);
|
||||
ABSL_DECLARE_FLAG(std::string, default_language);
|
||||
ABSL_DECLARE_FLAG(std::string, default_text_language);
|
||||
|
||||
#endif // PACKAGER_APP_MANIFEST_FLAGS_H_
|
||||
|
|
|
@ -8,46 +8,55 @@
|
|||
|
||||
#include "packager/app/mpd_flags.h"
|
||||
|
||||
DEFINE_bool(generate_static_live_mpd,
|
||||
false,
|
||||
"Set to true to generate static mpd. If segment_template is "
|
||||
"specified in stream descriptors, shaka-packager generates dynamic "
|
||||
"mpd by default; if this flag is enabled, shaka-packager generates "
|
||||
"static mpd instead. Note that if segment_template is not "
|
||||
"specified, shaka-packager always generates static mpd regardless "
|
||||
"of the value of this flag.");
|
||||
DEFINE_bool(output_media_info,
|
||||
false,
|
||||
"Create a human readable format of MediaInfo. The output file name "
|
||||
"will be the name specified by output flag, suffixed with "
|
||||
"'.media_info'.");
|
||||
DEFINE_string(mpd_output, "", "MPD output file name.");
|
||||
DEFINE_string(base_urls,
|
||||
"",
|
||||
"Comma separated BaseURLs for the MPD. The values will be added "
|
||||
"as <BaseURL> element(s) immediately under the <MPD> element.");
|
||||
DEFINE_double(min_buffer_time,
|
||||
2.0,
|
||||
"Specifies, in seconds, a common duration used in the definition "
|
||||
"of the MPD Representation data rate.");
|
||||
DEFINE_double(minimum_update_period,
|
||||
5.0,
|
||||
"Indicates to the player how often to refresh the media "
|
||||
"presentation description in seconds. This value is used for "
|
||||
"dynamic MPD only.");
|
||||
DEFINE_double(suggested_presentation_delay,
|
||||
0.0,
|
||||
"Specifies a delay, in seconds, to be added to the media "
|
||||
"presentation time. This value is used for dynamic MPD only.");
|
||||
DEFINE_string(utc_timings,
|
||||
"",
|
||||
"Comma separated UTCTiming schemeIdUri and value pairs for the "
|
||||
"MPD. This value is used for dynamic MPD only.");
|
||||
DEFINE_bool(generate_dash_if_iop_compliant_mpd,
|
||||
true,
|
||||
"Try to generate DASH-IF IOP compliant MPD. This is best effort "
|
||||
"and does not guarantee compliance.");
|
||||
DEFINE_bool(
|
||||
ABSL_FLAG(bool,
|
||||
generate_static_live_mpd,
|
||||
false,
|
||||
"Set to true to generate static mpd. If segment_template is "
|
||||
"specified in stream descriptors, shaka-packager generates dynamic "
|
||||
"mpd by default; if this flag is enabled, shaka-packager generates "
|
||||
"static mpd instead. Note that if segment_template is not "
|
||||
"specified, shaka-packager always generates static mpd regardless "
|
||||
"of the value of this flag.");
|
||||
ABSL_FLAG(bool,
|
||||
output_media_info,
|
||||
false,
|
||||
"Create a human readable format of MediaInfo. The output file name "
|
||||
"will be the name specified by output flag, suffixed with "
|
||||
"'.media_info'.");
|
||||
ABSL_FLAG(std::string, mpd_output, "", "MPD output file name.");
|
||||
ABSL_FLAG(std::string,
|
||||
base_urls,
|
||||
"",
|
||||
"Comma separated BaseURLs for the MPD. The values will be added "
|
||||
"as <BaseURL> element(s) immediately under the <MPD> element.");
|
||||
ABSL_FLAG(double,
|
||||
min_buffer_time,
|
||||
2.0,
|
||||
"Specifies, in seconds, a common duration used in the definition "
|
||||
"of the MPD Representation data rate.");
|
||||
ABSL_FLAG(double,
|
||||
minimum_update_period,
|
||||
5.0,
|
||||
"Indicates to the player how often to refresh the media "
|
||||
"presentation description in seconds. This value is used for "
|
||||
"dynamic MPD only.");
|
||||
ABSL_FLAG(double,
|
||||
suggested_presentation_delay,
|
||||
0.0,
|
||||
"Specifies a delay, in seconds, to be added to the media "
|
||||
"presentation time. This value is used for dynamic MPD only.");
|
||||
ABSL_FLAG(std::string,
|
||||
utc_timings,
|
||||
"",
|
||||
"Comma separated UTCTiming schemeIdUri and value pairs for the "
|
||||
"MPD. This value is used for dynamic MPD only.");
|
||||
ABSL_FLAG(bool,
|
||||
generate_dash_if_iop_compliant_mpd,
|
||||
true,
|
||||
"Try to generate DASH-IF IOP compliant MPD. This is best effort "
|
||||
"and does not guarantee compliance.");
|
||||
ABSL_FLAG(
|
||||
bool,
|
||||
allow_approximate_segment_timeline,
|
||||
false,
|
||||
"For live profile only. "
|
||||
|
@ -59,23 +68,27 @@ DEFINE_bool(
|
|||
"completely."
|
||||
"Ignored if $Time$ is used in segment template, since $Time$ requires "
|
||||
"accurate Segment Timeline.");
|
||||
DEFINE_bool(allow_codec_switching,
|
||||
false,
|
||||
"If enabled, allow adaptive switching between different codecs, "
|
||||
"if they have the same language, media type (audio, video etc) and "
|
||||
"container type.");
|
||||
DEFINE_bool(include_mspr_pro_for_playready,
|
||||
true,
|
||||
"If enabled, PlayReady Object <mspr:pro> will be inserted into "
|
||||
"<ContentProtection ...> element alongside with <cenc:pssh> "
|
||||
"when using PlayReady protection system.");
|
||||
DEFINE_bool(dash_force_segment_list,
|
||||
false,
|
||||
"Uses SegmentList instead of SegmentBase. Use this if the "
|
||||
"content is huge and the total number of (sub)segment references "
|
||||
"is greater than what the sidx atom allows (65535). Currently "
|
||||
"this flag is only supported in DASH ondemand profile.");
|
||||
DEFINE_bool(
|
||||
ABSL_FLAG(bool,
|
||||
allow_codec_switching,
|
||||
false,
|
||||
"If enabled, allow adaptive switching between different codecs, "
|
||||
"if they have the same language, media type (audio, video etc) and "
|
||||
"container type.");
|
||||
ABSL_FLAG(bool,
|
||||
include_mspr_pro_for_playready,
|
||||
true,
|
||||
"If enabled, PlayReady Object <mspr:pro> will be inserted into "
|
||||
"<ContentProtection ...> element alongside with <cenc:pssh> "
|
||||
"when using PlayReady protection system.");
|
||||
ABSL_FLAG(bool,
|
||||
dash_force_segment_list,
|
||||
false,
|
||||
"Uses SegmentList instead of SegmentBase. Use this if the "
|
||||
"content is huge and the total number of (sub)segment references "
|
||||
"is greater than what the sidx atom allows (65535). Currently "
|
||||
"this flag is only supported in DASH ondemand profile.");
|
||||
ABSL_FLAG(
|
||||
bool,
|
||||
low_latency_dash_mode,
|
||||
false,
|
||||
"If enabled, LL-DASH streaming will be used, "
|
||||
|
|
|
@ -9,21 +9,22 @@
|
|||
#ifndef APP_MPD_FLAGS_H_
|
||||
#define APP_MPD_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_bool(generate_static_live_mpd);
|
||||
DECLARE_bool(output_media_info);
|
||||
DECLARE_string(mpd_output);
|
||||
DECLARE_string(base_urls);
|
||||
DECLARE_double(minimum_update_period);
|
||||
DECLARE_double(min_buffer_time);
|
||||
DECLARE_double(suggested_presentation_delay);
|
||||
DECLARE_string(utc_timings);
|
||||
DECLARE_bool(generate_dash_if_iop_compliant_mpd);
|
||||
DECLARE_bool(allow_approximate_segment_timeline);
|
||||
DECLARE_bool(allow_codec_switching);
|
||||
DECLARE_bool(include_mspr_pro_for_playready);
|
||||
DECLARE_bool(dash_force_segment_list);
|
||||
DECLARE_bool(low_latency_dash_mode);
|
||||
ABSL_DECLARE_FLAG(bool, generate_static_live_mpd);
|
||||
ABSL_DECLARE_FLAG(bool, output_media_info);
|
||||
ABSL_DECLARE_FLAG(std::string, mpd_output);
|
||||
ABSL_DECLARE_FLAG(std::string, base_urls);
|
||||
ABSL_DECLARE_FLAG(double, minimum_update_period);
|
||||
ABSL_DECLARE_FLAG(double, min_buffer_time);
|
||||
ABSL_DECLARE_FLAG(double, suggested_presentation_delay);
|
||||
ABSL_DECLARE_FLAG(std::string, utc_timings);
|
||||
ABSL_DECLARE_FLAG(bool, generate_dash_if_iop_compliant_mpd);
|
||||
ABSL_DECLARE_FLAG(bool, allow_approximate_segment_timeline);
|
||||
ABSL_DECLARE_FLAG(bool, allow_codec_switching);
|
||||
ABSL_DECLARE_FLAG(bool, include_mspr_pro_for_playready);
|
||||
ABSL_DECLARE_FLAG(bool, dash_force_segment_list);
|
||||
ABSL_DECLARE_FLAG(bool, low_latency_dash_mode);
|
||||
|
||||
#endif // APP_MPD_FLAGS_H_
|
||||
|
|
|
@ -5,15 +5,14 @@
|
|||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <absl/strings/str_split.h>
|
||||
#include <glog/logging.h>
|
||||
#include "absl/flags/parse.h"
|
||||
#include "absl/flags/usage.h"
|
||||
#include "absl/flags/usage_config.h"
|
||||
#include "packager/app/mpd_generator_flags.h"
|
||||
#include "packager/app/vlog_flags.h"
|
||||
#include "packager/base/at_exit.h"
|
||||
#include "packager/base/command_line.h"
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_split.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include "packager/mpd/util/mpd_writer.h"
|
||||
#include "packager/tools/license_notice.h"
|
||||
#include "packager/version/version.h"
|
||||
|
@ -23,10 +22,11 @@
|
|||
#include <functional>
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
DEFINE_bool(licenses, false, "Dump licenses.");
|
||||
DEFINE_string(test_packager_version,
|
||||
"",
|
||||
"Packager version for testing. Should be used for testing only.");
|
||||
ABSL_FLAG(bool, licenses, false, "Dump licenses.");
|
||||
ABSL_FLAG(std::string,
|
||||
test_packager_version,
|
||||
"",
|
||||
"Packager version for testing. Should be used for testing only.");
|
||||
|
||||
namespace shaka {
|
||||
namespace {
|
||||
|
@ -51,12 +51,12 @@ enum ExitStatus {
|
|||
};
|
||||
|
||||
ExitStatus CheckRequiredFlags() {
|
||||
if (FLAGS_input.empty()) {
|
||||
if (absl::GetFlag(FLAGS_input).empty()) {
|
||||
LOG(ERROR) << "--input is required.";
|
||||
return kEmptyInputError;
|
||||
}
|
||||
|
||||
if (FLAGS_output.empty()) {
|
||||
if (absl::GetFlag(FLAGS_output).empty()) {
|
||||
LOG(ERROR) << "--output is required.";
|
||||
return kEmptyOutputError;
|
||||
}
|
||||
|
@ -69,12 +69,12 @@ ExitStatus RunMpdGenerator() {
|
|||
std::vector<std::string> base_urls;
|
||||
typedef std::vector<std::string>::const_iterator Iterator;
|
||||
|
||||
std::vector<std::string> input_files = base::SplitString(
|
||||
FLAGS_input, ",", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
|
||||
std::vector<std::string> input_files =
|
||||
absl::StrSplit(absl::GetFlag(FLAGS_input), ",", absl::AllowEmpty());
|
||||
|
||||
if (!FLAGS_base_urls.empty()) {
|
||||
base_urls = base::SplitString(FLAGS_base_urls, ",", base::KEEP_WHITESPACE,
|
||||
base::SPLIT_WANT_ALL);
|
||||
if (!absl::GetFlag(FLAGS_base_urls).empty()) {
|
||||
base_urls =
|
||||
absl::StrSplit(absl::GetFlag(FLAGS_base_urls), ",", absl::AllowEmpty());
|
||||
}
|
||||
|
||||
MpdWriter mpd_writer;
|
||||
|
@ -87,8 +87,8 @@ ExitStatus RunMpdGenerator() {
|
|||
}
|
||||
}
|
||||
|
||||
if (!mpd_writer.WriteMpdToFile(FLAGS_output.c_str())) {
|
||||
LOG(ERROR) << "Failed to write MPD to " << FLAGS_output;
|
||||
if (!mpd_writer.WriteMpdToFile(absl::GetFlag(FLAGS_output).c_str())) {
|
||||
LOG(ERROR) << "Failed to write MPD to " << absl::GetFlag(FLAGS_output);
|
||||
return kFailedToWriteMpdToFileError;
|
||||
}
|
||||
|
||||
|
@ -96,19 +96,19 @@ ExitStatus RunMpdGenerator() {
|
|||
}
|
||||
|
||||
int MpdMain(int argc, char** argv) {
|
||||
base::AtExitManager exit;
|
||||
// Needed to enable VLOG/DVLOG through --vmodule or --v.
|
||||
base::CommandLine::Init(argc, argv);
|
||||
absl::FlagsUsageConfig flag_config;
|
||||
flag_config.version_string = []() -> std::string {
|
||||
return "mpd_generator version " + GetPackagerVersion() + "\n";
|
||||
};
|
||||
flag_config.contains_help_flags =
|
||||
[](absl::string_view flag_file_name) -> bool { return true; };
|
||||
absl::SetFlagsUsageConfig(flag_config);
|
||||
|
||||
// Set up logging.
|
||||
logging::LoggingSettings log_settings;
|
||||
log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
CHECK(logging::InitLogging(log_settings));
|
||||
auto usage = absl::StrFormat(kUsage, argv[0]);
|
||||
absl::SetProgramUsageMessage(usage);
|
||||
absl::ParseCommandLine(argc, argv);
|
||||
|
||||
google::SetVersionString(GetPackagerVersion());
|
||||
google::SetUsageMessage(base::StringPrintf(kUsage, argv[0]));
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
if (FLAGS_licenses) {
|
||||
if (absl::GetFlag(FLAGS_licenses)) {
|
||||
for (const char* line : kLicenseNotice)
|
||||
std::cout << line << std::endl;
|
||||
return kSuccess;
|
||||
|
@ -116,12 +116,12 @@ int MpdMain(int argc, char** argv) {
|
|||
|
||||
ExitStatus status = CheckRequiredFlags();
|
||||
if (status != kSuccess) {
|
||||
google::ShowUsageWithFlags("Usage");
|
||||
std::cerr << "Usage " << absl::ProgramUsageMessage();
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!FLAGS_test_packager_version.empty())
|
||||
SetPackagerVersionForTesting(FLAGS_test_packager_version);
|
||||
if (!absl::GetFlag(FLAGS_test_packager_version).empty())
|
||||
SetPackagerVersionForTesting(absl::GetFlag(FLAGS_test_packager_version));
|
||||
|
||||
return RunMpdGenerator();
|
||||
}
|
||||
|
|
|
@ -7,12 +7,16 @@
|
|||
#ifndef APP_MPD_GENERATOR_FLAGS_H_
|
||||
#define APP_MPD_GENERATOR_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DEFINE_string(input, "", "Comma separated list of MediaInfo input files.");
|
||||
DEFINE_string(output, "", "MPD output file name.");
|
||||
DEFINE_string(base_urls,
|
||||
"",
|
||||
"Comma separated BaseURLs for the MPD. The values will be added "
|
||||
"as <BaseURL> element(s) immediately under the <MPD> element.");
|
||||
ABSL_FLAG(std::string,
|
||||
input,
|
||||
"",
|
||||
"Comma separated list of MediaInfo input files.");
|
||||
ABSL_FLAG(std::string, output, "", "MPD output file name.");
|
||||
ABSL_FLAG(std::string,
|
||||
base_urls,
|
||||
"",
|
||||
"Comma separated BaseURLs for the MPD. The values will be added "
|
||||
"as <BaseURL> element(s) immediately under the <MPD> element.");
|
||||
#endif // APP_MPD_GENERATOR_FLAGS_H_
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "packager/app/muxer_factory.h"
|
||||
|
||||
#include "packager/base/time/clock.h"
|
||||
#include <chrono>
|
||||
#include "packager/media/base/muxer.h"
|
||||
#include "packager/media/base/muxer_options.h"
|
||||
#include "packager/media/formats/mp2t/ts_muxer.h"
|
||||
|
@ -80,7 +80,7 @@ std::shared_ptr<Muxer> MuxerFactory::CreateMuxer(
|
|||
return muxer;
|
||||
}
|
||||
|
||||
void MuxerFactory::OverrideClock(base::Clock* clock) {
|
||||
void MuxerFactory::OverrideClock(Clock* clock) {
|
||||
clock_ = clock;
|
||||
}
|
||||
} // namespace media
|
||||
|
|
|
@ -12,10 +12,7 @@
|
|||
|
||||
#include "packager/media/base/container_names.h"
|
||||
#include "packager/media/public/mp4_output_params.h"
|
||||
|
||||
namespace base {
|
||||
class Clock;
|
||||
} // namespace base
|
||||
#include "packager/mpd/base/mpd_builder.h"
|
||||
|
||||
namespace shaka {
|
||||
struct PackagingParams;
|
||||
|
@ -40,7 +37,7 @@ class MuxerFactory {
|
|||
|
||||
/// For testing, if you need to replace the clock that muxers work with
|
||||
/// this will replace the clock for all muxers created after this call.
|
||||
void OverrideClock(base::Clock* clock);
|
||||
void OverrideClock(Clock* clock);
|
||||
|
||||
void SetTsStreamOffset(int32_t offset_ms) {
|
||||
transport_stream_timestamp_offset_ms_ = offset_ms;
|
||||
|
@ -53,7 +50,7 @@ class MuxerFactory {
|
|||
const Mp4OutputParams mp4_params_;
|
||||
const std::string temp_dir_;
|
||||
int32_t transport_stream_timestamp_offset_ms_ = 0;
|
||||
base::Clock* clock_ = nullptr;
|
||||
Clock* clock_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
|
|
|
@ -8,48 +8,57 @@
|
|||
|
||||
#include "packager/app/muxer_flags.h"
|
||||
|
||||
DEFINE_double(clear_lead,
|
||||
5.0f,
|
||||
"Clear lead in seconds if encryption is enabled. Note that we do "
|
||||
"not support partial segment encryption, so it is rounded up to "
|
||||
"full segments. Set it to a value smaller than segment_duration "
|
||||
"so only the first segment is in clear since the first segment "
|
||||
"could be smaller than segment_duration if there is small "
|
||||
"non-zero starting timestamp.");
|
||||
DEFINE_double(segment_duration,
|
||||
6.0f,
|
||||
"Segment duration in seconds. If single_segment is specified, "
|
||||
"this parameter sets the duration of a subsegment; otherwise, "
|
||||
"this parameter sets the duration of a segment. Actual segment "
|
||||
"durations may not be exactly as requested.");
|
||||
DEFINE_bool(segment_sap_aligned,
|
||||
true,
|
||||
"Force segments to begin with stream access points.");
|
||||
DEFINE_double(fragment_duration,
|
||||
0,
|
||||
"Fragment duration in seconds. Should not be larger than "
|
||||
"the segment duration. Actual fragment durations may not be "
|
||||
"exactly as requested.");
|
||||
DEFINE_bool(fragment_sap_aligned,
|
||||
true,
|
||||
"Force fragments to begin with stream access points. This flag "
|
||||
"implies segment_sap_aligned.");
|
||||
DEFINE_bool(generate_sidx_in_media_segments,
|
||||
true,
|
||||
"Indicates whether to generate 'sidx' box in media segments. Note "
|
||||
"that it is required for DASH on-demand profile (not using segment "
|
||||
"template).");
|
||||
DEFINE_string(temp_dir,
|
||||
"",
|
||||
"Specify a directory in which to store temporary (intermediate) "
|
||||
" files. Used only if single_segment=true.");
|
||||
DEFINE_bool(mp4_include_pssh_in_stream,
|
||||
true,
|
||||
"MP4 only: include pssh in the encrypted stream.");
|
||||
DEFINE_int32(transport_stream_timestamp_offset_ms,
|
||||
100,
|
||||
"A positive value, in milliseconds, by which output timestamps "
|
||||
"are offset to compensate for possible negative timestamps in the "
|
||||
"input. For example, timestamps from ISO-BMFF after adjusted by "
|
||||
"EditList could be negative. In transport streams, timestamps are "
|
||||
"not allowed to be less than zero.");
|
||||
ABSL_FLAG(double,
|
||||
clear_lead,
|
||||
5.0f,
|
||||
"Clear lead in seconds if encryption is enabled. Note that we do "
|
||||
"not support partial segment encryption, so it is rounded up to "
|
||||
"full segments. Set it to a value smaller than segment_duration "
|
||||
"so only the first segment is in clear since the first segment "
|
||||
"could be smaller than segment_duration if there is small "
|
||||
"non-zero starting timestamp.");
|
||||
ABSL_FLAG(double,
|
||||
segment_duration,
|
||||
6.0f,
|
||||
"Segment duration in seconds. If single_segment is specified, "
|
||||
"this parameter sets the duration of a subsegment; otherwise, "
|
||||
"this parameter sets the duration of a segment. Actual segment "
|
||||
"durations may not be exactly as requested.");
|
||||
ABSL_FLAG(bool,
|
||||
segment_sap_aligned,
|
||||
true,
|
||||
"Force segments to begin with stream access points.");
|
||||
ABSL_FLAG(double,
|
||||
fragment_duration,
|
||||
0,
|
||||
"Fragment duration in seconds. Should not be larger than "
|
||||
"the segment duration. Actual fragment durations may not be "
|
||||
"exactly as requested.");
|
||||
ABSL_FLAG(bool,
|
||||
fragment_sap_aligned,
|
||||
true,
|
||||
"Force fragments to begin with stream access points. This flag "
|
||||
"implies segment_sap_aligned.");
|
||||
ABSL_FLAG(bool,
|
||||
generate_sidx_in_media_segments,
|
||||
true,
|
||||
"Indicates whether to generate 'sidx' box in media segments. Note "
|
||||
"that it is required for DASH on-demand profile (not using segment "
|
||||
"template).");
|
||||
ABSL_FLAG(std::string,
|
||||
temp_dir,
|
||||
"",
|
||||
"Specify a directory in which to store temporary (intermediate) "
|
||||
" files. Used only if single_segment=true.");
|
||||
ABSL_FLAG(bool,
|
||||
mp4_include_pssh_in_stream,
|
||||
true,
|
||||
"MP4 only: include pssh in the encrypted stream.");
|
||||
ABSL_FLAG(int32_t,
|
||||
transport_stream_timestamp_offset_ms,
|
||||
100,
|
||||
"A positive value, in milliseconds, by which output timestamps "
|
||||
"are offset to compensate for possible negative timestamps in the "
|
||||
"input. For example, timestamps from ISO-BMFF after adjusted by "
|
||||
"EditList could be negative. In transport streams, timestamps are "
|
||||
"not allowed to be less than zero.");
|
||||
|
|
|
@ -9,16 +9,17 @@
|
|||
#ifndef APP_MUXER_FLAGS_H_
|
||||
#define APP_MUXER_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_double(clear_lead);
|
||||
DECLARE_double(segment_duration);
|
||||
DECLARE_bool(segment_sap_aligned);
|
||||
DECLARE_double(fragment_duration);
|
||||
DECLARE_bool(fragment_sap_aligned);
|
||||
DECLARE_bool(generate_sidx_in_media_segments);
|
||||
DECLARE_string(temp_dir);
|
||||
DECLARE_bool(mp4_include_pssh_in_stream);
|
||||
DECLARE_int32(transport_stream_timestamp_offset_ms);
|
||||
ABSL_DECLARE_FLAG(double, clear_lead);
|
||||
ABSL_DECLARE_FLAG(double, segment_duration);
|
||||
ABSL_DECLARE_FLAG(bool, segment_sap_aligned);
|
||||
ABSL_DECLARE_FLAG(double, fragment_duration);
|
||||
ABSL_DECLARE_FLAG(bool, fragment_sap_aligned);
|
||||
ABSL_DECLARE_FLAG(bool, generate_sidx_in_media_segments);
|
||||
ABSL_DECLARE_FLAG(std::string, temp_dir);
|
||||
ABSL_DECLARE_FLAG(bool, mp4_include_pssh_in_stream);
|
||||
ABSL_DECLARE_FLAG(int32_t, transport_stream_timestamp_offset_ms);
|
||||
|
||||
#endif // APP_MUXER_FLAGS_H_
|
||||
|
|
|
@ -4,53 +4,56 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/flag.h>
|
||||
#include <iostream>
|
||||
#include <locale>
|
||||
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <absl/strings/str_split.h>
|
||||
#include <glog/logging.h>
|
||||
#include <optional>
|
||||
#include "absl/flags/parse.h"
|
||||
#include "absl/flags/usage.h"
|
||||
#include "absl/flags/usage_config.h"
|
||||
#include "packager/app/ad_cue_generator_flags.h"
|
||||
#include "packager/app/crypto_flags.h"
|
||||
#include "packager/app/hls_flags.h"
|
||||
#include "packager/app/manifest_flags.h"
|
||||
#include "packager/app/mpd_flags.h"
|
||||
#include "packager/app/muxer_flags.h"
|
||||
#include "packager/app/packager_util.h"
|
||||
#include "packager/app/playready_key_encryption_flags.h"
|
||||
#include "packager/app/protection_system_flags.h"
|
||||
#include "packager/app/raw_key_encryption_flags.h"
|
||||
#include "packager/app/stream_descriptor.h"
|
||||
#include "packager/app/vlog_flags.h"
|
||||
#include "packager/app/widevine_encryption_flags.h"
|
||||
#include "packager/base/command_line.h"
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/optional.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/string_split.h"
|
||||
#include "packager/base/strings/string_util.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/packager.h"
|
||||
#include "packager/kv_pairs/kv_pairs.h"
|
||||
#include "packager/tools/license_notice.h"
|
||||
#include "packager/utils/string_trim_split.h"
|
||||
#include "retired_flags.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <codecvt>
|
||||
#include <functional>
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
DEFINE_bool(dump_stream_info, false, "Dump demuxed stream info.");
|
||||
DEFINE_bool(licenses, false, "Dump licenses.");
|
||||
DEFINE_bool(quiet, false, "When enabled, LOG(INFO) output is suppressed.");
|
||||
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_string(test_packager_version,
|
||||
"",
|
||||
"Packager version for testing. Should be used for testing only.");
|
||||
DEFINE_bool(single_threaded,
|
||||
false,
|
||||
"If enabled, only use one thread when generating content.");
|
||||
ABSL_FLAG(bool, dump_stream_info, false, "Dump demuxed stream info.");
|
||||
ABSL_FLAG(bool, licenses, false, "Dump licenses.");
|
||||
ABSL_FLAG(bool, quiet, false, "When enabled, LOG(INFO) output is suppressed.");
|
||||
ABSL_FLAG(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.");
|
||||
ABSL_FLAG(std::string,
|
||||
test_packager_version,
|
||||
"",
|
||||
"Packager version for testing. Should be used for testing only.");
|
||||
ABSL_FLAG(bool,
|
||||
single_threaded,
|
||||
false,
|
||||
"If enabled, only use one thread when generating content.");
|
||||
|
||||
namespace shaka {
|
||||
namespace {
|
||||
|
@ -131,17 +134,18 @@ enum ExitStatus {
|
|||
};
|
||||
|
||||
bool GetWidevineSigner(WidevineSigner* signer) {
|
||||
signer->signer_name = FLAGS_signer;
|
||||
if (!FLAGS_aes_signing_key_bytes.empty()) {
|
||||
signer->signer_name = absl::GetFlag(FLAGS_signer);
|
||||
if (!absl::GetFlag(FLAGS_aes_signing_key).bytes.empty()) {
|
||||
signer->signing_key_type = WidevineSigner::SigningKeyType::kAes;
|
||||
signer->aes.key = FLAGS_aes_signing_key_bytes;
|
||||
signer->aes.iv = FLAGS_aes_signing_iv_bytes;
|
||||
} else if (!FLAGS_rsa_signing_key_path.empty()) {
|
||||
signer->aes.key = absl::GetFlag(FLAGS_aes_signing_key).bytes;
|
||||
signer->aes.iv = absl::GetFlag(FLAGS_aes_signing_iv).bytes;
|
||||
} else if (!absl::GetFlag(FLAGS_rsa_signing_key_path).empty()) {
|
||||
signer->signing_key_type = WidevineSigner::SigningKeyType::kRsa;
|
||||
if (!File::ReadFileToString(FLAGS_rsa_signing_key_path.c_str(),
|
||||
&signer->rsa.key)) {
|
||||
LOG(ERROR) << "Failed to read from '" << FLAGS_rsa_signing_key_path
|
||||
<< "'.";
|
||||
if (!File::ReadFileToString(
|
||||
absl::GetFlag(FLAGS_rsa_signing_key_path).c_str(),
|
||||
&signer->rsa.key)) {
|
||||
LOG(ERROR) << "Failed to read from '"
|
||||
<< absl::GetFlag(FLAGS_rsa_signing_key_path) << "'.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -150,11 +154,11 @@ bool GetWidevineSigner(WidevineSigner* signer) {
|
|||
|
||||
bool GetHlsPlaylistType(const std::string& playlist_type,
|
||||
HlsPlaylistType* playlist_type_enum) {
|
||||
if (base::ToUpperASCII(playlist_type) == "VOD") {
|
||||
if (absl::AsciiStrToUpper(playlist_type) == "VOD") {
|
||||
*playlist_type_enum = HlsPlaylistType::kVod;
|
||||
} else if (base::ToUpperASCII(playlist_type) == "LIVE") {
|
||||
} else if (absl::AsciiStrToUpper(playlist_type) == "LIVE") {
|
||||
*playlist_type_enum = HlsPlaylistType::kLive;
|
||||
} else if (base::ToUpperASCII(playlist_type) == "EVENT") {
|
||||
} else if (absl::AsciiStrToUpper(playlist_type) == "EVENT") {
|
||||
*playlist_type_enum = HlsPlaylistType::kEvent;
|
||||
} else {
|
||||
LOG(ERROR) << "Unrecognized playlist type " << playlist_type;
|
||||
|
@ -164,31 +168,33 @@ bool GetHlsPlaylistType(const std::string& playlist_type,
|
|||
}
|
||||
|
||||
bool GetProtectionScheme(uint32_t* protection_scheme) {
|
||||
if (FLAGS_protection_scheme == "cenc") {
|
||||
if (absl::GetFlag(FLAGS_protection_scheme) == "cenc") {
|
||||
*protection_scheme = EncryptionParams::kProtectionSchemeCenc;
|
||||
return true;
|
||||
}
|
||||
if (FLAGS_protection_scheme == "cbc1") {
|
||||
if (absl::GetFlag(FLAGS_protection_scheme) == "cbc1") {
|
||||
*protection_scheme = EncryptionParams::kProtectionSchemeCbc1;
|
||||
return true;
|
||||
}
|
||||
if (FLAGS_protection_scheme == "cbcs") {
|
||||
if (absl::GetFlag(FLAGS_protection_scheme) == "cbcs") {
|
||||
*protection_scheme = EncryptionParams::kProtectionSchemeCbcs;
|
||||
return true;
|
||||
}
|
||||
if (FLAGS_protection_scheme == "cens") {
|
||||
if (absl::GetFlag(FLAGS_protection_scheme) == "cens") {
|
||||
*protection_scheme = EncryptionParams::kProtectionSchemeCens;
|
||||
return true;
|
||||
}
|
||||
LOG(ERROR) << "Unrecognized protection_scheme " << FLAGS_protection_scheme;
|
||||
LOG(ERROR) << "Unrecognized protection_scheme "
|
||||
<< absl::GetFlag(FLAGS_protection_scheme);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ParseKeys(const std::string& keys, RawKeyParams* raw_key) {
|
||||
for (const std::string& key_data : base::SplitString(
|
||||
keys, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
|
||||
base::StringPairs string_pairs;
|
||||
base::SplitStringIntoKeyValuePairs(key_data, '=', ':', &string_pairs);
|
||||
std::vector<std::string> keys_data = SplitAndTrimSkipEmpty(keys, ',');
|
||||
|
||||
for (const std::string& key_data : keys_data) {
|
||||
std::vector<KVPair> string_pairs =
|
||||
SplitStringIntoKeyValuePairs(key_data, '=', ':');
|
||||
|
||||
std::map<std::string, std::string> value_map;
|
||||
for (const auto& string_pair : string_pairs)
|
||||
|
@ -200,13 +206,14 @@ bool ParseKeys(const std::string& keys, RawKeyParams* raw_key) {
|
|||
}
|
||||
auto& key_info = raw_key->key_map[drm_label];
|
||||
if (value_map[kKeyIdLabel].empty() ||
|
||||
!base::HexStringToBytes(value_map[kKeyIdLabel], &key_info.key_id)) {
|
||||
!shaka::ValidHexStringToBytes(value_map[kKeyIdLabel],
|
||||
&key_info.key_id)) {
|
||||
LOG(ERROR) << "Empty key id or invalid hex string for key id: "
|
||||
<< value_map[kKeyIdLabel];
|
||||
return false;
|
||||
}
|
||||
if (value_map[kKeyLabel].empty() ||
|
||||
!base::HexStringToBytes(value_map[kKeyLabel], &key_info.key)) {
|
||||
!shaka::ValidHexStringToBytes(value_map[kKeyLabel], &key_info.key)) {
|
||||
LOG(ERROR) << "Empty key or invalid hex string for key: "
|
||||
<< value_map[kKeyLabel];
|
||||
return false;
|
||||
|
@ -216,7 +223,7 @@ bool ParseKeys(const std::string& keys, RawKeyParams* raw_key) {
|
|||
LOG(ERROR) << "IV already specified with --iv";
|
||||
return false;
|
||||
}
|
||||
if (!base::HexStringToBytes(value_map[kKeyIvLabel], &key_info.iv)) {
|
||||
if (!shaka::ValidHexStringToBytes(value_map[kKeyIvLabel], &key_info.iv)) {
|
||||
LOG(ERROR) << "Empty IV or invalid hex string for IV: "
|
||||
<< value_map[kKeyIvLabel];
|
||||
return false;
|
||||
|
@ -227,18 +234,18 @@ bool ParseKeys(const std::string& keys, RawKeyParams* raw_key) {
|
|||
}
|
||||
|
||||
bool GetRawKeyParams(RawKeyParams* raw_key) {
|
||||
raw_key->iv = FLAGS_iv_bytes;
|
||||
raw_key->pssh = FLAGS_pssh_bytes;
|
||||
if (!FLAGS_keys.empty()) {
|
||||
if (!ParseKeys(FLAGS_keys, raw_key)) {
|
||||
LOG(ERROR) << "Failed to parse --keys " << FLAGS_keys;
|
||||
raw_key->iv = absl::GetFlag(FLAGS_iv).bytes;
|
||||
raw_key->pssh = absl::GetFlag(FLAGS_pssh).bytes;
|
||||
if (!absl::GetFlag(FLAGS_keys).empty()) {
|
||||
if (!ParseKeys(absl::GetFlag(FLAGS_keys), raw_key)) {
|
||||
LOG(ERROR) << "Failed to parse --keys " << absl::GetFlag(FLAGS_keys);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// An empty StreamLabel specifies the default key info.
|
||||
RawKeyParams::KeyInfo& key_info = raw_key->key_map[""];
|
||||
key_info.key_id = FLAGS_key_id_bytes;
|
||||
key_info.key = FLAGS_key_bytes;
|
||||
key_info.key_id = absl::GetFlag(FLAGS_key_id).bytes;
|
||||
key_info.key = absl::GetFlag(FLAGS_key).bytes;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -246,26 +253,25 @@ bool GetRawKeyParams(RawKeyParams* raw_key) {
|
|||
bool ParseAdCues(const std::string& ad_cues, std::vector<Cuepoint>* cuepoints) {
|
||||
// Track if optional field is supplied consistently across all cue points.
|
||||
size_t duration_count = 0;
|
||||
std::vector<std::string> ad_cues_vec = SplitAndTrimSkipEmpty(ad_cues, ';');
|
||||
|
||||
for (const std::string& ad_cue : base::SplitString(
|
||||
ad_cues, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
|
||||
for (const std::string& ad_cue : ad_cues_vec) {
|
||||
Cuepoint cuepoint;
|
||||
auto split_ad_cue = base::SplitString(ad_cue, ",", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
std::vector<std::string> split_ad_cue = SplitAndTrimSkipEmpty(ad_cue, ',');
|
||||
|
||||
if (split_ad_cue.size() > 2) {
|
||||
LOG(ERROR) << "Failed to parse --ad_cues " << ad_cues
|
||||
<< " Each ad cue must contain no more than 2 components.";
|
||||
}
|
||||
if (!base::StringToDouble(split_ad_cue.front(),
|
||||
&cuepoint.start_time_in_seconds)) {
|
||||
if (!absl::SimpleAtod(split_ad_cue.front(),
|
||||
&cuepoint.start_time_in_seconds)) {
|
||||
LOG(ERROR) << "Failed to parse --ad_cues " << ad_cues
|
||||
<< " Start time component must be of type double.";
|
||||
return false;
|
||||
}
|
||||
if (split_ad_cue.size() > 1) {
|
||||
duration_count++;
|
||||
if (!base::StringToDouble(split_ad_cue[1],
|
||||
&cuepoint.duration_in_seconds)) {
|
||||
if (!absl::SimpleAtod(split_ad_cue[1], &cuepoint.duration_in_seconds)) {
|
||||
LOG(ERROR) << "Failed to parse --ad_cues " << ad_cues
|
||||
<< " Duration component must be of type double.";
|
||||
return false;
|
||||
|
@ -296,9 +302,10 @@ bool ParseProtectionSystems(const std::string& protection_systems_str,
|
|||
{"widevine", ProtectionSystem::kWidevine},
|
||||
};
|
||||
|
||||
for (const std::string& protection_system :
|
||||
base::SplitString(base::ToLowerASCII(protection_systems_str), ",",
|
||||
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
|
||||
std::vector<std::string> protection_systems_vec =
|
||||
SplitAndTrimSkipEmpty(absl::AsciiStrToLower(protection_systems_str), ',');
|
||||
|
||||
for (const std::string& protection_system : protection_systems_vec) {
|
||||
auto iter = mapping.find(protection_system);
|
||||
if (iter == mapping.end()) {
|
||||
LOG(ERROR) << "Seeing unrecognized protection system: "
|
||||
|
@ -310,36 +317,42 @@ bool ParseProtectionSystems(const std::string& protection_systems_str,
|
|||
return true;
|
||||
}
|
||||
|
||||
base::Optional<PackagingParams> GetPackagingParams() {
|
||||
std::optional<PackagingParams> GetPackagingParams() {
|
||||
PackagingParams packaging_params;
|
||||
|
||||
packaging_params.temp_dir = FLAGS_temp_dir;
|
||||
packaging_params.single_threaded = FLAGS_single_threaded;
|
||||
packaging_params.temp_dir = absl::GetFlag(FLAGS_temp_dir);
|
||||
packaging_params.single_threaded = absl::GetFlag(FLAGS_single_threaded);
|
||||
|
||||
AdCueGeneratorParams& ad_cue_generator_params =
|
||||
packaging_params.ad_cue_generator_params;
|
||||
if (!ParseAdCues(FLAGS_ad_cues, &ad_cue_generator_params.cue_points)) {
|
||||
return base::nullopt;
|
||||
if (!ParseAdCues(absl::GetFlag(FLAGS_ad_cues),
|
||||
&ad_cue_generator_params.cue_points)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
ChunkingParams& chunking_params = packaging_params.chunking_params;
|
||||
chunking_params.segment_duration_in_seconds = FLAGS_segment_duration;
|
||||
chunking_params.subsegment_duration_in_seconds = FLAGS_fragment_duration;
|
||||
chunking_params.low_latency_dash_mode = FLAGS_low_latency_dash_mode;
|
||||
chunking_params.segment_sap_aligned = FLAGS_segment_sap_aligned;
|
||||
chunking_params.subsegment_sap_aligned = FLAGS_fragment_sap_aligned;
|
||||
chunking_params.segment_duration_in_seconds =
|
||||
absl::GetFlag(FLAGS_segment_duration);
|
||||
chunking_params.subsegment_duration_in_seconds =
|
||||
absl::GetFlag(FLAGS_fragment_duration);
|
||||
chunking_params.low_latency_dash_mode =
|
||||
absl::GetFlag(FLAGS_low_latency_dash_mode);
|
||||
chunking_params.segment_sap_aligned =
|
||||
absl::GetFlag(FLAGS_segment_sap_aligned);
|
||||
chunking_params.subsegment_sap_aligned =
|
||||
absl::GetFlag(FLAGS_fragment_sap_aligned);
|
||||
|
||||
int num_key_providers = 0;
|
||||
EncryptionParams& encryption_params = packaging_params.encryption_params;
|
||||
if (FLAGS_enable_widevine_encryption) {
|
||||
if (absl::GetFlag(FLAGS_enable_widevine_encryption)) {
|
||||
encryption_params.key_provider = KeyProvider::kWidevine;
|
||||
++num_key_providers;
|
||||
}
|
||||
if (FLAGS_enable_playready_encryption) {
|
||||
if (absl::GetFlag(FLAGS_enable_playready_encryption)) {
|
||||
encryption_params.key_provider = KeyProvider::kPlayReady;
|
||||
++num_key_providers;
|
||||
}
|
||||
if (FLAGS_enable_raw_key_encryption) {
|
||||
if (absl::GetFlag(FLAGS_enable_raw_key_encryption)) {
|
||||
encryption_params.key_provider = KeyProvider::kRawKey;
|
||||
++num_key_providers;
|
||||
}
|
||||
|
@ -347,52 +360,55 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
|||
LOG(ERROR) << "Only one of --enable_widevine_encryption, "
|
||||
"--enable_playready_encryption, "
|
||||
"--enable_raw_key_encryption can be enabled.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (!ParseProtectionSystems(FLAGS_protection_systems,
|
||||
if (!ParseProtectionSystems(absl::GetFlag(FLAGS_protection_systems),
|
||||
&encryption_params.protection_systems)) {
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (encryption_params.key_provider != KeyProvider::kNone) {
|
||||
encryption_params.clear_lead_in_seconds = FLAGS_clear_lead;
|
||||
encryption_params.clear_lead_in_seconds = absl::GetFlag(FLAGS_clear_lead);
|
||||
if (!GetProtectionScheme(&encryption_params.protection_scheme))
|
||||
return base::nullopt;
|
||||
encryption_params.crypt_byte_block = FLAGS_crypt_byte_block;
|
||||
encryption_params.skip_byte_block = FLAGS_skip_byte_block;
|
||||
return std::nullopt;
|
||||
encryption_params.crypt_byte_block = absl::GetFlag(FLAGS_crypt_byte_block);
|
||||
encryption_params.skip_byte_block = absl::GetFlag(FLAGS_skip_byte_block);
|
||||
|
||||
encryption_params.crypto_period_duration_in_seconds =
|
||||
FLAGS_crypto_period_duration;
|
||||
encryption_params.vp9_subsample_encryption = FLAGS_vp9_subsample_encryption;
|
||||
absl::GetFlag(FLAGS_crypto_period_duration);
|
||||
encryption_params.vp9_subsample_encryption =
|
||||
absl::GetFlag(FLAGS_vp9_subsample_encryption);
|
||||
encryption_params.stream_label_func = std::bind(
|
||||
&Packager::DefaultStreamLabelFunction, FLAGS_max_sd_pixels,
|
||||
FLAGS_max_hd_pixels, FLAGS_max_uhd1_pixels, std::placeholders::_1);
|
||||
&Packager::DefaultStreamLabelFunction,
|
||||
absl::GetFlag(FLAGS_max_sd_pixels), absl::GetFlag(FLAGS_max_hd_pixels),
|
||||
absl::GetFlag(FLAGS_max_uhd1_pixels), std::placeholders::_1);
|
||||
encryption_params.playready_extra_header_data =
|
||||
FLAGS_playready_extra_header_data;
|
||||
absl::GetFlag(FLAGS_playready_extra_header_data);
|
||||
}
|
||||
switch (encryption_params.key_provider) {
|
||||
case KeyProvider::kWidevine: {
|
||||
WidevineEncryptionParams& widevine = encryption_params.widevine;
|
||||
widevine.key_server_url = FLAGS_key_server_url;
|
||||
widevine.key_server_url = absl::GetFlag(FLAGS_key_server_url);
|
||||
|
||||
widevine.content_id = FLAGS_content_id_bytes;
|
||||
widevine.policy = FLAGS_policy;
|
||||
widevine.group_id = FLAGS_group_id_bytes;
|
||||
widevine.enable_entitlement_license = FLAGS_enable_entitlement_license;
|
||||
widevine.content_id = absl::GetFlag(FLAGS_content_id).bytes;
|
||||
widevine.policy = absl::GetFlag(FLAGS_policy);
|
||||
widevine.group_id = absl::GetFlag(FLAGS_group_id).bytes;
|
||||
widevine.enable_entitlement_license =
|
||||
absl::GetFlag(FLAGS_enable_entitlement_license);
|
||||
if (!GetWidevineSigner(&widevine.signer))
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
break;
|
||||
}
|
||||
case KeyProvider::kPlayReady: {
|
||||
PlayReadyEncryptionParams& playready = encryption_params.playready;
|
||||
playready.key_server_url = FLAGS_playready_server_url;
|
||||
playready.program_identifier = FLAGS_program_identifier;
|
||||
playready.key_server_url = absl::GetFlag(FLAGS_playready_server_url);
|
||||
playready.program_identifier = absl::GetFlag(FLAGS_program_identifier);
|
||||
break;
|
||||
}
|
||||
case KeyProvider::kRawKey: {
|
||||
if (!GetRawKeyParams(&encryption_params.raw_key))
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
break;
|
||||
}
|
||||
case KeyProvider::kNone:
|
||||
|
@ -401,30 +417,30 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
|||
|
||||
num_key_providers = 0;
|
||||
DecryptionParams& decryption_params = packaging_params.decryption_params;
|
||||
if (FLAGS_enable_widevine_decryption) {
|
||||
if (absl::GetFlag(FLAGS_enable_widevine_decryption)) {
|
||||
decryption_params.key_provider = KeyProvider::kWidevine;
|
||||
++num_key_providers;
|
||||
}
|
||||
if (FLAGS_enable_raw_key_decryption) {
|
||||
if (absl::GetFlag(FLAGS_enable_raw_key_decryption)) {
|
||||
decryption_params.key_provider = KeyProvider::kRawKey;
|
||||
++num_key_providers;
|
||||
}
|
||||
if (num_key_providers > 1) {
|
||||
LOG(ERROR) << "Only one of --enable_widevine_decryption, "
|
||||
"--enable_raw_key_decryption can be enabled.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
switch (decryption_params.key_provider) {
|
||||
case KeyProvider::kWidevine: {
|
||||
WidevineDecryptionParams& widevine = decryption_params.widevine;
|
||||
widevine.key_server_url = FLAGS_key_server_url;
|
||||
widevine.key_server_url = absl::GetFlag(FLAGS_key_server_url);
|
||||
if (!GetWidevineSigner(&widevine.signer))
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
break;
|
||||
}
|
||||
case KeyProvider::kRawKey: {
|
||||
if (!GetRawKeyParams(&decryption_params.raw_key))
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
break;
|
||||
}
|
||||
case KeyProvider::kPlayReady:
|
||||
|
@ -434,110 +450,125 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
|||
|
||||
Mp4OutputParams& mp4_params = packaging_params.mp4_output_params;
|
||||
mp4_params.generate_sidx_in_media_segments =
|
||||
FLAGS_generate_sidx_in_media_segments;
|
||||
mp4_params.include_pssh_in_stream = FLAGS_mp4_include_pssh_in_stream;
|
||||
mp4_params.low_latency_dash_mode = FLAGS_low_latency_dash_mode;
|
||||
absl::GetFlag(FLAGS_generate_sidx_in_media_segments);
|
||||
mp4_params.include_pssh_in_stream =
|
||||
absl::GetFlag(FLAGS_mp4_include_pssh_in_stream);
|
||||
mp4_params.low_latency_dash_mode = absl::GetFlag(FLAGS_low_latency_dash_mode);
|
||||
|
||||
packaging_params.transport_stream_timestamp_offset_ms =
|
||||
FLAGS_transport_stream_timestamp_offset_ms;
|
||||
absl::GetFlag(FLAGS_transport_stream_timestamp_offset_ms);
|
||||
|
||||
packaging_params.output_media_info = FLAGS_output_media_info;
|
||||
packaging_params.output_media_info = absl::GetFlag(FLAGS_output_media_info);
|
||||
|
||||
MpdParams& mpd_params = packaging_params.mpd_params;
|
||||
mpd_params.mpd_output = FLAGS_mpd_output;
|
||||
mpd_params.base_urls = base::SplitString(
|
||||
FLAGS_base_urls, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
mpd_params.min_buffer_time = FLAGS_min_buffer_time;
|
||||
mpd_params.minimum_update_period = FLAGS_minimum_update_period;
|
||||
mpd_params.suggested_presentation_delay = FLAGS_suggested_presentation_delay;
|
||||
mpd_params.time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
|
||||
mpd_params.preserved_segments_outside_live_window =
|
||||
FLAGS_preserved_segments_outside_live_window;
|
||||
mpd_params.use_segment_list = FLAGS_dash_force_segment_list;
|
||||
mpd_params.mpd_output = absl::GetFlag(FLAGS_mpd_output);
|
||||
|
||||
if (!FLAGS_utc_timings.empty()) {
|
||||
base::StringPairs pairs;
|
||||
if (!base::SplitStringIntoKeyValuePairs(FLAGS_utc_timings, '=', ',',
|
||||
&pairs)) {
|
||||
std::vector<std::string> base_urls =
|
||||
SplitAndTrimSkipEmpty(absl::GetFlag(FLAGS_base_urls), ',');
|
||||
|
||||
mpd_params.base_urls = base_urls;
|
||||
mpd_params.min_buffer_time = absl::GetFlag(FLAGS_min_buffer_time);
|
||||
mpd_params.minimum_update_period = absl::GetFlag(FLAGS_minimum_update_period);
|
||||
mpd_params.suggested_presentation_delay =
|
||||
absl::GetFlag(FLAGS_suggested_presentation_delay);
|
||||
mpd_params.time_shift_buffer_depth =
|
||||
absl::GetFlag(FLAGS_time_shift_buffer_depth);
|
||||
mpd_params.preserved_segments_outside_live_window =
|
||||
absl::GetFlag(FLAGS_preserved_segments_outside_live_window);
|
||||
mpd_params.use_segment_list = absl::GetFlag(FLAGS_dash_force_segment_list);
|
||||
|
||||
if (!absl::GetFlag(FLAGS_utc_timings).empty()) {
|
||||
std::vector<KVPair> pairs = SplitStringIntoKeyValuePairs(
|
||||
absl::GetFlag(FLAGS_utc_timings), '=', ',');
|
||||
if (pairs.empty()) {
|
||||
LOG(ERROR) << "Invalid --utc_timings scheme_id_uri/value pairs.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
for (const auto& string_pair : pairs) {
|
||||
mpd_params.utc_timings.push_back({string_pair.first, string_pair.second});
|
||||
}
|
||||
}
|
||||
|
||||
mpd_params.default_language = FLAGS_default_language;
|
||||
mpd_params.default_text_language = FLAGS_default_text_language;
|
||||
mpd_params.generate_static_live_mpd = FLAGS_generate_static_live_mpd;
|
||||
mpd_params.default_language = absl::GetFlag(FLAGS_default_language);
|
||||
mpd_params.default_text_language = absl::GetFlag(FLAGS_default_text_language);
|
||||
mpd_params.generate_static_live_mpd =
|
||||
absl::GetFlag(FLAGS_generate_static_live_mpd);
|
||||
mpd_params.generate_dash_if_iop_compliant_mpd =
|
||||
FLAGS_generate_dash_if_iop_compliant_mpd;
|
||||
absl::GetFlag(FLAGS_generate_dash_if_iop_compliant_mpd);
|
||||
mpd_params.allow_approximate_segment_timeline =
|
||||
FLAGS_allow_approximate_segment_timeline;
|
||||
mpd_params.allow_codec_switching = FLAGS_allow_codec_switching;
|
||||
mpd_params.include_mspr_pro = FLAGS_include_mspr_pro_for_playready;
|
||||
mpd_params.low_latency_dash_mode = FLAGS_low_latency_dash_mode;
|
||||
absl::GetFlag(FLAGS_allow_approximate_segment_timeline);
|
||||
mpd_params.allow_codec_switching = absl::GetFlag(FLAGS_allow_codec_switching);
|
||||
mpd_params.include_mspr_pro =
|
||||
absl::GetFlag(FLAGS_include_mspr_pro_for_playready);
|
||||
mpd_params.low_latency_dash_mode = absl::GetFlag(FLAGS_low_latency_dash_mode);
|
||||
|
||||
HlsParams& hls_params = packaging_params.hls_params;
|
||||
if (!GetHlsPlaylistType(FLAGS_hls_playlist_type, &hls_params.playlist_type)) {
|
||||
return base::nullopt;
|
||||
if (!GetHlsPlaylistType(absl::GetFlag(FLAGS_hls_playlist_type),
|
||||
&hls_params.playlist_type)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
hls_params.master_playlist_output = FLAGS_hls_master_playlist_output;
|
||||
hls_params.base_url = FLAGS_hls_base_url;
|
||||
hls_params.key_uri = FLAGS_hls_key_uri;
|
||||
hls_params.time_shift_buffer_depth = FLAGS_time_shift_buffer_depth;
|
||||
hls_params.master_playlist_output =
|
||||
absl::GetFlag(FLAGS_hls_master_playlist_output);
|
||||
hls_params.base_url = absl::GetFlag(FLAGS_hls_base_url);
|
||||
hls_params.key_uri = absl::GetFlag(FLAGS_hls_key_uri);
|
||||
hls_params.time_shift_buffer_depth =
|
||||
absl::GetFlag(FLAGS_time_shift_buffer_depth);
|
||||
hls_params.preserved_segments_outside_live_window =
|
||||
FLAGS_preserved_segments_outside_live_window;
|
||||
hls_params.default_language = FLAGS_default_language;
|
||||
hls_params.default_text_language = FLAGS_default_text_language;
|
||||
hls_params.media_sequence_number = FLAGS_hls_media_sequence_number;
|
||||
absl::GetFlag(FLAGS_preserved_segments_outside_live_window);
|
||||
hls_params.default_language = absl::GetFlag(FLAGS_default_language);
|
||||
hls_params.default_text_language = absl::GetFlag(FLAGS_default_text_language);
|
||||
hls_params.media_sequence_number =
|
||||
absl::GetFlag(FLAGS_hls_media_sequence_number);
|
||||
|
||||
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_test_packager_version.empty())
|
||||
test_params.injected_library_version = FLAGS_test_packager_version;
|
||||
test_params.dump_stream_info = absl::GetFlag(FLAGS_dump_stream_info);
|
||||
test_params.inject_fake_clock = absl::GetFlag(FLAGS_use_fake_clock_for_muxer);
|
||||
if (!absl::GetFlag(FLAGS_test_packager_version).empty())
|
||||
test_params.injected_library_version =
|
||||
absl::GetFlag(FLAGS_test_packager_version);
|
||||
|
||||
return packaging_params;
|
||||
}
|
||||
|
||||
int PackagerMain(int argc, char** argv) {
|
||||
// Needed to enable VLOG/DVLOG through --vmodule or --v.
|
||||
base::CommandLine::Init(argc, argv);
|
||||
absl::FlagsUsageConfig flag_config;
|
||||
flag_config.version_string = []() -> std::string {
|
||||
return "packager version " + shaka::Packager::GetLibraryVersion() + "\n";
|
||||
};
|
||||
flag_config.contains_help_flags =
|
||||
[](absl::string_view flag_file_name) -> bool { return true; };
|
||||
absl::SetFlagsUsageConfig(flag_config);
|
||||
|
||||
// Set up logging.
|
||||
logging::LoggingSettings log_settings;
|
||||
log_settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
CHECK(logging::InitLogging(log_settings));
|
||||
auto usage = absl::StrFormat(kUsage, argv[0]);
|
||||
absl::SetProgramUsageMessage(usage);
|
||||
|
||||
google::SetVersionString(shaka::Packager::GetLibraryVersion());
|
||||
google::SetUsageMessage(base::StringPrintf(kUsage, argv[0]));
|
||||
google::ParseCommandLineFlags(&argc, &argv, true);
|
||||
if (FLAGS_licenses) {
|
||||
auto remaining_args = absl::ParseCommandLine(argc, argv);
|
||||
if (absl::GetFlag(FLAGS_licenses)) {
|
||||
for (const char* line : kLicenseNotice)
|
||||
std::cout << line << std::endl;
|
||||
return kSuccess;
|
||||
}
|
||||
if (argc < 2) {
|
||||
google::ShowUsageWithFlags("Usage");
|
||||
if (remaining_args.size() < 2) {
|
||||
std::cerr << "Usage: " << absl::ProgramUsageMessage();
|
||||
return kSuccess;
|
||||
}
|
||||
if (FLAGS_quiet)
|
||||
logging::SetMinLogLevel(logging::LOG_WARNING);
|
||||
if (absl::GetFlag(FLAGS_quiet))
|
||||
google::SetStderrLogging(google::GLOG_WARNING);
|
||||
|
||||
if (!ValidateWidevineCryptoFlags() || !ValidateRawKeyCryptoFlags() ||
|
||||
!ValidatePRCryptoFlags()) {
|
||||
!ValidatePRCryptoFlags() || !ValidateCryptoFlags() ||
|
||||
!ValidateRetiredFlags()) {
|
||||
return kArgumentValidationFailed;
|
||||
}
|
||||
|
||||
base::Optional<PackagingParams> packaging_params = GetPackagingParams();
|
||||
std::optional<PackagingParams> packaging_params = GetPackagingParams();
|
||||
if (!packaging_params)
|
||||
return kArgumentValidationFailed;
|
||||
|
||||
std::vector<StreamDescriptor> stream_descriptors;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
base::Optional<StreamDescriptor> stream_descriptor =
|
||||
ParseStreamDescriptor(argv[i]);
|
||||
for (size_t i = 1; i < remaining_args.size(); ++i) {
|
||||
std::optional<StreamDescriptor> stream_descriptor =
|
||||
ParseStreamDescriptor(remaining_args[i]);
|
||||
if (!stream_descriptor)
|
||||
return kArgumentValidationFailed;
|
||||
stream_descriptors.push_back(stream_descriptor.value());
|
||||
|
@ -554,7 +585,7 @@ int PackagerMain(int argc, char** argv) {
|
|||
LOG(ERROR) << "Packaging Error: " << status.ToString();
|
||||
return kPackagingFailed;
|
||||
}
|
||||
if (!FLAGS_quiet)
|
||||
if (!absl::GetFlag(FLAGS_quiet))
|
||||
printf("Packaging completed successfully.\n");
|
||||
return kSuccess;
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
|
||||
#include "packager/app/packager_util.h"
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/string_split.h"
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <absl/strings/str_split.h>
|
||||
#include <glog/logging.h>
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/media/base/media_handler.h"
|
||||
#include "packager/media/base/muxer_options.h"
|
||||
|
@ -17,7 +17,7 @@
|
|||
#include "packager/media/base/request_signer.h"
|
||||
#include "packager/media/base/widevine_key_source.h"
|
||||
#include "packager/mpd/base/mpd_options.h"
|
||||
#include "packager/status.h"
|
||||
#include "packager/status/status.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
|
|
|
@ -10,12 +10,18 @@
|
|||
|
||||
#include "packager/app/validate_flag.h"
|
||||
|
||||
DEFINE_bool(enable_playready_encryption,
|
||||
false,
|
||||
"Enable encryption with PlayReady key.");
|
||||
DEFINE_string(playready_server_url, "", "PlayReady packaging server url.");
|
||||
DEFINE_string(program_identifier, "",
|
||||
"Program identifier for packaging request.");
|
||||
ABSL_FLAG(bool,
|
||||
enable_playready_encryption,
|
||||
false,
|
||||
"Enable encryption with PlayReady key.");
|
||||
ABSL_FLAG(std::string,
|
||||
playready_server_url,
|
||||
"",
|
||||
"PlayReady packaging server url.");
|
||||
ABSL_FLAG(std::string,
|
||||
program_identifier,
|
||||
"",
|
||||
"Program identifier for packaging request.");
|
||||
|
||||
namespace shaka {
|
||||
namespace {
|
||||
|
@ -26,13 +32,15 @@ bool ValidatePRCryptoFlags() {
|
|||
bool success = true;
|
||||
|
||||
const char playready_label[] = "--enable_playready_encryption";
|
||||
bool playready_enabled = FLAGS_enable_playready_encryption;
|
||||
if (!ValidateFlag("playready_server_url", FLAGS_playready_server_url,
|
||||
bool playready_enabled = absl::GetFlag(FLAGS_enable_playready_encryption);
|
||||
if (!ValidateFlag("playready_server_url",
|
||||
absl::GetFlag(FLAGS_playready_server_url),
|
||||
playready_enabled, !kFlagIsOptional, playready_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (!ValidateFlag("program_identifier", FLAGS_program_identifier,
|
||||
playready_enabled, !kFlagIsOptional, playready_label)) {
|
||||
if (!ValidateFlag("program_identifier",
|
||||
absl::GetFlag(FLAGS_program_identifier), playready_enabled,
|
||||
!kFlagIsOptional, playready_label)) {
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
#ifndef APP_PLAYREADY_KEY_ENCRYPTION_FLAGS_H_
|
||||
#define APP_PLAYREADY_KEY_ENCRYPTION_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
#include "packager/app/gflags_hex_bytes.h"
|
||||
|
||||
DECLARE_bool(enable_playready_encryption);
|
||||
DECLARE_string(playready_server_url);
|
||||
DECLARE_string(program_identifier);
|
||||
ABSL_DECLARE_FLAG(bool, enable_playready_encryption);
|
||||
ABSL_DECLARE_FLAG(std::string, playready_server_url);
|
||||
ABSL_DECLARE_FLAG(std::string, program_identifier);
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
#include "packager/app/protection_system_flags.h"
|
||||
|
||||
DEFINE_string(
|
||||
ABSL_FLAG(
|
||||
std::string,
|
||||
protection_systems,
|
||||
"",
|
||||
"Protection systems to be generated. Supported protection systems include "
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
#ifndef PACKAGER_APP_PROTECTION_SYSTEM_FLAGS_H_
|
||||
#define PACKAGER_APP_PROTECTION_SYSTEM_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_string(protection_systems);
|
||||
ABSL_DECLARE_FLAG(std::string, protection_systems);
|
||||
|
||||
#endif // PACKAGER_APP_PROTECTION_SYSTEM_FLAGS_H_
|
||||
|
|
|
@ -6,93 +6,104 @@
|
|||
//
|
||||
// Defines command line flags for raw key encryption/decryption.
|
||||
|
||||
#include "packager/app/raw_key_encryption_flags.h"
|
||||
#include "packager/utils/absl_flag_hexbytes.h"
|
||||
|
||||
#include "packager/app/validate_flag.h"
|
||||
|
||||
DEFINE_bool(enable_fixed_key_encryption,
|
||||
false,
|
||||
"Same as --enable_raw_key_encryption. Will be deprecated.");
|
||||
DEFINE_bool(enable_fixed_key_decryption,
|
||||
false,
|
||||
"Same as --enable_raw_key_decryption. Will be deprecated.");
|
||||
DEFINE_bool(enable_raw_key_encryption,
|
||||
false,
|
||||
"Enable encryption with raw key (key provided in command line).");
|
||||
DEFINE_bool(enable_raw_key_decryption,
|
||||
false,
|
||||
"Enable decryption with raw key (key provided in command line).");
|
||||
DEFINE_hex_bytes(
|
||||
key_id,
|
||||
"",
|
||||
"Key id in hex string format. Will be deprecated. Use --keys.");
|
||||
DEFINE_hex_bytes(key,
|
||||
"",
|
||||
"Key in hex string format. Will be deprecated. Use --keys.");
|
||||
DEFINE_string(keys,
|
||||
"",
|
||||
"A list of key information in the form of label=<drm "
|
||||
"label>:key_id=<32-digit key id in hex>:key=<32-digit key in "
|
||||
"hex>,label=...");
|
||||
DEFINE_hex_bytes(
|
||||
iv,
|
||||
"",
|
||||
"IV in hex string format. If not specified, a random IV will be "
|
||||
"generated. This flag should only be used for testing.");
|
||||
DEFINE_hex_bytes(
|
||||
pssh,
|
||||
"",
|
||||
"One or more PSSH boxes in hex string format. If not specified, "
|
||||
"will generate a v1 common PSSH box as specified in "
|
||||
"https://goo.gl/s8RIhr.");
|
||||
ABSL_FLAG(bool,
|
||||
enable_fixed_key_encryption,
|
||||
false,
|
||||
"Same as --enable_raw_key_encryption. Will be deprecated.");
|
||||
ABSL_FLAG(bool,
|
||||
enable_fixed_key_decryption,
|
||||
false,
|
||||
"Same as --enable_raw_key_decryption. Will be deprecated.");
|
||||
ABSL_FLAG(bool,
|
||||
enable_raw_key_encryption,
|
||||
false,
|
||||
"Enable encryption with raw key (key provided in command line).");
|
||||
ABSL_FLAG(bool,
|
||||
enable_raw_key_decryption,
|
||||
false,
|
||||
"Enable decryption with raw key (key provided in command line).");
|
||||
ABSL_FLAG(shaka::HexBytes,
|
||||
key_id,
|
||||
{},
|
||||
"Key id in hex string format. Will be deprecated. Use --keys.");
|
||||
ABSL_FLAG(shaka::HexBytes,
|
||||
key,
|
||||
{},
|
||||
"Key in hex string format. Will be deprecated. Use --keys.");
|
||||
ABSL_FLAG(std::string,
|
||||
keys,
|
||||
"",
|
||||
"A list of key information in the form of label=<drm "
|
||||
"label>:key_id=<32-digit key id in hex>:key=<32-digit key in "
|
||||
"hex>,label=...");
|
||||
ABSL_FLAG(shaka::HexBytes,
|
||||
iv,
|
||||
{},
|
||||
"IV in hex string format. If not specified, a random IV will be "
|
||||
"generated. This flag should only be used for testing.");
|
||||
ABSL_FLAG(shaka::HexBytes,
|
||||
pssh,
|
||||
{},
|
||||
"One or more PSSH boxes in hex string format. If not specified, "
|
||||
"will generate a v1 common PSSH box as specified in "
|
||||
"https://goo.gl/s8RIhr.");
|
||||
|
||||
namespace shaka {
|
||||
|
||||
bool ValidateRawKeyCryptoFlags() {
|
||||
bool success = true;
|
||||
|
||||
if (FLAGS_enable_fixed_key_encryption)
|
||||
FLAGS_enable_raw_key_encryption = true;
|
||||
if (FLAGS_enable_fixed_key_decryption)
|
||||
FLAGS_enable_raw_key_decryption = true;
|
||||
if (FLAGS_enable_fixed_key_encryption || FLAGS_enable_fixed_key_decryption) {
|
||||
if (absl::GetFlag(FLAGS_enable_fixed_key_encryption))
|
||||
absl::SetFlag(&FLAGS_enable_raw_key_encryption, true);
|
||||
if (absl::GetFlag(FLAGS_enable_fixed_key_decryption))
|
||||
absl::SetFlag(&FLAGS_enable_raw_key_decryption, true);
|
||||
if (absl::GetFlag(FLAGS_enable_fixed_key_encryption) ||
|
||||
absl::GetFlag(FLAGS_enable_fixed_key_decryption)) {
|
||||
PrintWarning(
|
||||
"--enable_fixed_key_encryption and --enable_fixed_key_decryption are "
|
||||
"going to be deprecated. Please switch to --enable_raw_key_encryption "
|
||||
"and --enable_raw_key_decryption as soon as possible.");
|
||||
}
|
||||
|
||||
const bool raw_key_crypto =
|
||||
FLAGS_enable_raw_key_encryption || FLAGS_enable_raw_key_decryption;
|
||||
const bool raw_key_crypto = absl::GetFlag(FLAGS_enable_raw_key_encryption) ||
|
||||
absl::GetFlag(FLAGS_enable_raw_key_decryption);
|
||||
const char raw_key_crypto_label[] = "--enable_raw_key_encryption/decryption";
|
||||
// --key_id and --key are associated with --enable_raw_key_encryption and
|
||||
// --enable_raw_key_decryption.
|
||||
if (FLAGS_keys.empty()) {
|
||||
if (!ValidateFlag("key_id", FLAGS_key_id_bytes, raw_key_crypto, false,
|
||||
raw_key_crypto_label)) {
|
||||
if (absl::GetFlag(FLAGS_keys).empty()) {
|
||||
if (!ValidateFlag("key_id", absl::GetFlag(FLAGS_key_id).bytes,
|
||||
raw_key_crypto, false, raw_key_crypto_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (!ValidateFlag("key", FLAGS_key_bytes, raw_key_crypto, false,
|
||||
raw_key_crypto_label)) {
|
||||
if (!ValidateFlag("key", absl::GetFlag(FLAGS_key).bytes, raw_key_crypto,
|
||||
false, raw_key_crypto_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (success && (!FLAGS_key_id_bytes.empty() || !FLAGS_key_bytes.empty())) {
|
||||
if (success && (!absl::GetFlag(FLAGS_key_id).bytes.empty() ||
|
||||
!absl::GetFlag(FLAGS_key).bytes.empty())) {
|
||||
PrintWarning(
|
||||
"--key_id and --key are going to be deprecated. Please switch to "
|
||||
"--keys as soon as possible.");
|
||||
}
|
||||
} else {
|
||||
if (!FLAGS_key_id_bytes.empty() || !FLAGS_key_bytes.empty()) {
|
||||
if (!absl::GetFlag(FLAGS_key_id).bytes.empty() ||
|
||||
!absl::GetFlag(FLAGS_key).bytes.empty()) {
|
||||
PrintError("--key_id or --key cannot be used together with --keys.");
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
if (!ValidateFlag("iv", FLAGS_iv_bytes, FLAGS_enable_raw_key_encryption, true,
|
||||
if (!ValidateFlag("iv", absl::GetFlag(FLAGS_iv).bytes,
|
||||
absl::GetFlag(FLAGS_enable_raw_key_encryption), true,
|
||||
"--enable_raw_key_encryption")) {
|
||||
success = false;
|
||||
}
|
||||
if (!FLAGS_iv_bytes.empty()) {
|
||||
if (FLAGS_iv_bytes.size() != 8 && FLAGS_iv_bytes.size() != 16) {
|
||||
if (!absl::GetFlag(FLAGS_iv).bytes.empty()) {
|
||||
if (absl::GetFlag(FLAGS_iv).bytes.size() != 8 &&
|
||||
absl::GetFlag(FLAGS_iv).bytes.size() != 16) {
|
||||
PrintError(
|
||||
"--iv should be either 8 bytes (16 hex digits) or 16 bytes (32 hex "
|
||||
"digits).");
|
||||
|
@ -101,8 +112,9 @@ bool ValidateRawKeyCryptoFlags() {
|
|||
}
|
||||
|
||||
// --pssh is associated with --enable_raw_key_encryption.
|
||||
if (!ValidateFlag("pssh", FLAGS_pssh_bytes, FLAGS_enable_raw_key_encryption,
|
||||
true, "--enable_raw_key_encryption")) {
|
||||
if (!ValidateFlag("pssh", absl::GetFlag(FLAGS_pssh).bytes,
|
||||
absl::GetFlag(FLAGS_enable_raw_key_encryption), true,
|
||||
"--enable_raw_key_encryption")) {
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
|
|
|
@ -9,17 +9,18 @@
|
|||
#ifndef PACKAGER_APP_RAW_KEY_ENCRYPTION_FLAGS_H_
|
||||
#define PACKAGER_APP_RAW_KEY_ENCRYPTION_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
#include "packager/app/gflags_hex_bytes.h"
|
||||
#include "packager/utils/absl_flag_hexbytes.h"
|
||||
|
||||
DECLARE_bool(enable_raw_key_encryption);
|
||||
DECLARE_bool(enable_raw_key_decryption);
|
||||
DECLARE_hex_bytes(key_id);
|
||||
DECLARE_hex_bytes(key);
|
||||
DECLARE_string(keys);
|
||||
DECLARE_hex_bytes(iv);
|
||||
DECLARE_hex_bytes(pssh);
|
||||
ABSL_DECLARE_FLAG(bool, enable_raw_key_encryption);
|
||||
ABSL_DECLARE_FLAG(bool, enable_raw_key_decryption);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, key_id);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, key);
|
||||
ABSL_DECLARE_FLAG(std::string, keys);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, iv);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, pssh);
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
|
|
@ -11,42 +11,52 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
DEFINE_string(profile, "", "This flag is deprecated. Do not use.");
|
||||
DEFINE_bool(single_segment, true, "This flag is deprecated. Do not use.");
|
||||
DEFINE_bool(webm_subsample_encryption,
|
||||
true,
|
||||
"This flag is deprecated. Use vp9_subsample_encryption instead.");
|
||||
DEFINE_double(availability_time_offset,
|
||||
0,
|
||||
"This flag is deprecated. Use suggested_presentation_delay "
|
||||
"instead which can achieve similar effect.");
|
||||
DEFINE_string(playready_key_id,
|
||||
"",
|
||||
"This flag is deprecated. Use --enable_raw_key_encryption with "
|
||||
"--generate_playready_pssh to generate PlayReady PSSH.");
|
||||
DEFINE_string(playready_key,
|
||||
"",
|
||||
"This flag is deprecated. Use --enable_raw_key_encryption with "
|
||||
"--generate_playready_pssh to generate PlayReady PSSH.");
|
||||
DEFINE_bool(mp4_use_decoding_timestamp_in_timeline,
|
||||
false,
|
||||
"This flag is deprecated. Do not use.");
|
||||
DEFINE_int32(
|
||||
ABSL_FLAG(std::string, profile, "", "This flag is deprecated. Do not use.");
|
||||
ABSL_FLAG(bool, single_segment, true, "This flag is deprecated. Do not use.");
|
||||
ABSL_FLAG(bool,
|
||||
webm_subsample_encryption,
|
||||
true,
|
||||
"This flag is deprecated. Use vp9_subsample_encryption instead.");
|
||||
ABSL_FLAG(double,
|
||||
availability_time_offset,
|
||||
0,
|
||||
"This flag is deprecated. Use suggested_presentation_delay "
|
||||
"instead which can achieve similar effect.");
|
||||
ABSL_FLAG(std::string,
|
||||
playready_key_id,
|
||||
"",
|
||||
"This flag is deprecated. Use --enable_raw_key_encryption with "
|
||||
"--generate_playready_pssh to generate PlayReady PSSH.");
|
||||
ABSL_FLAG(std::string,
|
||||
playready_key,
|
||||
"",
|
||||
"This flag is deprecated. Use --enable_raw_key_encryption with "
|
||||
"--generate_playready_pssh to generate PlayReady PSSH.");
|
||||
ABSL_FLAG(bool,
|
||||
mp4_use_decoding_timestamp_in_timeline,
|
||||
false,
|
||||
"This flag is deprecated. Do not use.");
|
||||
ABSL_FLAG(
|
||||
int32_t,
|
||||
num_subsegments_per_sidx,
|
||||
0,
|
||||
"This flag is deprecated. Use --generate_sidx_in_media_segments instead.");
|
||||
DEFINE_bool(generate_widevine_pssh,
|
||||
false,
|
||||
"This flag is deprecated. Use --protection_systems instead.");
|
||||
DEFINE_bool(generate_playready_pssh,
|
||||
false,
|
||||
"This flag is deprecated. Use --protection_systems instead.");
|
||||
DEFINE_bool(generate_common_pssh,
|
||||
false,
|
||||
"This flag is deprecated. Use --protection_systems instead.");
|
||||
DEFINE_bool(generate_static_mpd,
|
||||
false,
|
||||
"This flag is deprecated. Use --generate_static_live_mpd instead.");
|
||||
ABSL_FLAG(bool,
|
||||
generate_widevine_pssh,
|
||||
false,
|
||||
"This flag is deprecated. Use --protection_systems instead.");
|
||||
ABSL_FLAG(bool,
|
||||
generate_playready_pssh,
|
||||
false,
|
||||
"This flag is deprecated. Use --protection_systems instead.");
|
||||
ABSL_FLAG(bool,
|
||||
generate_common_pssh,
|
||||
false,
|
||||
"This flag is deprecated. Use --protection_systems instead.");
|
||||
ABSL_FLAG(bool,
|
||||
generate_static_mpd,
|
||||
false,
|
||||
"This flag is deprecated. Use --generate_static_live_mpd instead.");
|
||||
|
||||
// The current gflags library does not provide a way to check whether a flag is
|
||||
// set in command line. If a flag has a different value to its default value,
|
||||
|
@ -102,16 +112,70 @@ bool InformRetiredGenerateStaticMpdFlag(const char* flagname, bool value) {
|
|||
return true;
|
||||
}
|
||||
|
||||
DEFINE_validator(profile, &InformRetiredStringFlag);
|
||||
DEFINE_validator(single_segment, &InformRetiredDefaultTrueFlag);
|
||||
DEFINE_validator(webm_subsample_encryption, &InformRetiredDefaultTrueFlag);
|
||||
DEFINE_validator(availability_time_offset, &InformRetiredDefaultDoubleFlag);
|
||||
DEFINE_validator(playready_key_id, &InformRetiredStringFlag);
|
||||
DEFINE_validator(playready_key, &InformRetiredStringFlag);
|
||||
DEFINE_validator(mp4_use_decoding_timestamp_in_timeline,
|
||||
&InformRetiredDefaultFalseFlag);
|
||||
DEFINE_validator(num_subsegments_per_sidx, &InformRetiredDefaultInt32Flag);
|
||||
DEFINE_validator(generate_widevine_pssh, &InformRetiredPsshGenerationFlag);
|
||||
DEFINE_validator(generate_playready_pssh, &InformRetiredPsshGenerationFlag);
|
||||
DEFINE_validator(generate_common_pssh, &InformRetiredPsshGenerationFlag);
|
||||
DEFINE_validator(generate_static_mpd, &InformRetiredGenerateStaticMpdFlag);
|
||||
namespace shaka {
|
||||
bool ValidateRetiredFlags() {
|
||||
bool success = true;
|
||||
|
||||
auto profile = absl::GetFlag(FLAGS_profile);
|
||||
if (!InformRetiredStringFlag("profile", profile)) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
auto single_segment = absl::GetFlag(FLAGS_single_segment);
|
||||
if (!InformRetiredDefaultTrueFlag("single_segment", single_segment)) {
|
||||
success = false;
|
||||
}
|
||||
auto webm_subsample_encryption =
|
||||
absl::GetFlag(FLAGS_webm_subsample_encryption);
|
||||
if (!InformRetiredDefaultTrueFlag("webm_subsample_encryption",
|
||||
webm_subsample_encryption)) {
|
||||
success = false;
|
||||
}
|
||||
auto availability_time_offset = absl::GetFlag(FLAGS_availability_time_offset);
|
||||
if (!InformRetiredDefaultDoubleFlag("availability_time_offset",
|
||||
availability_time_offset)) {
|
||||
success = false;
|
||||
}
|
||||
auto playready_key_id = absl::GetFlag(FLAGS_playready_key_id);
|
||||
if (!InformRetiredStringFlag("playready_key_id", playready_key_id)) {
|
||||
success = false;
|
||||
}
|
||||
auto playready_key = absl::GetFlag(FLAGS_playready_key);
|
||||
if (!InformRetiredStringFlag("playready_key", playready_key)) {
|
||||
success = false;
|
||||
}
|
||||
auto mp4_use_decoding_timestamp_in_timeline =
|
||||
absl::GetFlag(FLAGS_mp4_use_decoding_timestamp_in_timeline);
|
||||
if (!InformRetiredDefaultFalseFlag("mp4_use_decoding_timestamp_in_timeline",
|
||||
mp4_use_decoding_timestamp_in_timeline)) {
|
||||
success = false;
|
||||
}
|
||||
auto num_subsegments_per_sidx = absl::GetFlag(FLAGS_num_subsegments_per_sidx);
|
||||
if (!InformRetiredDefaultInt32Flag("num_subsegments_per_sidx",
|
||||
num_subsegments_per_sidx)) {
|
||||
success = false;
|
||||
}
|
||||
auto generate_widevine_pssh = absl::GetFlag(FLAGS_generate_widevine_pssh);
|
||||
if (!InformRetiredPsshGenerationFlag("generate_widevine_pssh",
|
||||
generate_widevine_pssh)) {
|
||||
success = false;
|
||||
}
|
||||
auto generate_playready_pssh = absl::GetFlag(FLAGS_generate_playready_pssh);
|
||||
if (!InformRetiredPsshGenerationFlag("generate_playready_pssh",
|
||||
generate_playready_pssh)) {
|
||||
success = false;
|
||||
}
|
||||
auto generate_common_pssh = absl::GetFlag(FLAGS_generate_common_pssh);
|
||||
if (!InformRetiredPsshGenerationFlag("generate_common_pssh",
|
||||
generate_common_pssh)) {
|
||||
success = false;
|
||||
}
|
||||
auto generate_static_mpd = absl::GetFlag(FLAGS_generate_static_mpd);
|
||||
if (!InformRetiredGenerateStaticMpdFlag("generate_static_mpd",
|
||||
generate_static_mpd)) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
} // namespace shaka
|
||||
|
|
|
@ -4,16 +4,21 @@
|
|||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_string(profile);
|
||||
DECLARE_bool(single_segment);
|
||||
DECLARE_bool(webm_subsample_encryption);
|
||||
DECLARE_double(availability_time_offset);
|
||||
DECLARE_string(playready_key_id);
|
||||
DECLARE_string(playready_key);
|
||||
DECLARE_bool(mp4_use_decoding_timestamp_in_timeline);
|
||||
DECLARE_int32(num_subsegments_per_sidx);
|
||||
DECLARE_bool(generate_widevine_pssh);
|
||||
DECLARE_bool(generate_playready_pssh);
|
||||
DECLARE_bool(generate_common_pssh);
|
||||
ABSL_DECLARE_FLAG(std::string, profile);
|
||||
ABSL_DECLARE_FLAG(bool, single_segment);
|
||||
ABSL_DECLARE_FLAG(bool, webm_subsample_encryption);
|
||||
ABSL_DECLARE_FLAG(double, availability_time_offset);
|
||||
ABSL_DECLARE_FLAG(std::string, playready_key_id);
|
||||
ABSL_DECLARE_FLAG(std::string, playready_key);
|
||||
ABSL_DECLARE_FLAG(bool, mp4_use_decoding_timestamp_in_timeline);
|
||||
ABSL_DECLARE_FLAG(int32_t, num_subsegments_per_sidx);
|
||||
ABSL_DECLARE_FLAG(bool, generate_widevine_pssh);
|
||||
ABSL_DECLARE_FLAG(bool, generate_playready_pssh);
|
||||
ABSL_DECLARE_FLAG(bool, generate_common_pssh);
|
||||
|
||||
namespace shaka {
|
||||
bool ValidateRetiredFlags();
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "packager/app/stream_descriptor.h"
|
||||
#include "packager/kv_pairs/kv_pairs.h"
|
||||
#include "packager/utils/string_trim_split.h"
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/string_split.h"
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <absl/strings/str_split.h>
|
||||
#include <glog/logging.h>
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
@ -86,7 +88,7 @@ const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
|
|||
};
|
||||
|
||||
FieldType GetFieldType(const std::string& field_name) {
|
||||
for (size_t idx = 0; idx < arraysize(kFieldNameTypeMappings); ++idx) {
|
||||
for (size_t idx = 0; idx < std::size(kFieldNameTypeMappings); ++idx) {
|
||||
if (field_name == kFieldNameTypeMappings[idx].field_name)
|
||||
return kFieldNameTypeMappings[idx].field_type;
|
||||
}
|
||||
|
@ -95,162 +97,162 @@ FieldType GetFieldType(const std::string& field_name) {
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
base::Optional<StreamDescriptor> ParseStreamDescriptor(
|
||||
std::optional<StreamDescriptor> ParseStreamDescriptor(
|
||||
const std::string& descriptor_string) {
|
||||
StreamDescriptor descriptor;
|
||||
|
||||
// Split descriptor string into name/value pairs.
|
||||
base::StringPairs pairs;
|
||||
if (!base::SplitStringIntoKeyValuePairs(descriptor_string, '=', ',',
|
||||
&pairs)) {
|
||||
std::vector<KVPair> kv_pairs =
|
||||
SplitStringIntoKeyValuePairs(descriptor_string, '=', ',');
|
||||
if (kv_pairs.empty()) {
|
||||
LOG(ERROR) << "Invalid stream descriptors name/value pairs: "
|
||||
<< descriptor_string;
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
for (base::StringPairs::const_iterator iter = pairs.begin();
|
||||
iter != pairs.end(); ++iter) {
|
||||
switch (GetFieldType(iter->first)) {
|
||||
std::vector<absl::string_view> tokens;
|
||||
|
||||
for (const auto& pair : kv_pairs) {
|
||||
switch (GetFieldType(pair.first)) {
|
||||
case kStreamSelectorField:
|
||||
descriptor.stream_selector = iter->second;
|
||||
descriptor.stream_selector = pair.second;
|
||||
break;
|
||||
case kInputField:
|
||||
descriptor.input = iter->second;
|
||||
descriptor.input = pair.second;
|
||||
break;
|
||||
case kOutputField:
|
||||
descriptor.output = iter->second;
|
||||
descriptor.output = pair.second;
|
||||
break;
|
||||
case kSegmentTemplateField:
|
||||
descriptor.segment_template = iter->second;
|
||||
descriptor.segment_template = pair.second;
|
||||
break;
|
||||
case kBandwidthField: {
|
||||
unsigned bw;
|
||||
if (!base::StringToUint(iter->second, &bw)) {
|
||||
if (!absl::SimpleAtoi(pair.second, &bw)) {
|
||||
LOG(ERROR) << "Non-numeric bandwidth specified.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
descriptor.bandwidth = bw;
|
||||
break;
|
||||
}
|
||||
case kLanguageField: {
|
||||
descriptor.language = iter->second;
|
||||
descriptor.language = pair.second;
|
||||
break;
|
||||
}
|
||||
case kCcIndexField: {
|
||||
unsigned index;
|
||||
if (!base::StringToUint(iter->second, &index)) {
|
||||
if (!absl::SimpleAtoi(pair.second, &index)) {
|
||||
LOG(ERROR) << "Non-numeric cc_index specified.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
descriptor.cc_index = index;
|
||||
break;
|
||||
}
|
||||
case kOutputFormatField: {
|
||||
descriptor.output_format = iter->second;
|
||||
descriptor.output_format = pair.second;
|
||||
break;
|
||||
}
|
||||
case kHlsNameField: {
|
||||
descriptor.hls_name = iter->second;
|
||||
descriptor.hls_name = pair.second;
|
||||
break;
|
||||
}
|
||||
case kHlsGroupIdField: {
|
||||
descriptor.hls_group_id = iter->second;
|
||||
descriptor.hls_group_id = pair.second;
|
||||
break;
|
||||
}
|
||||
case kHlsPlaylistNameField: {
|
||||
descriptor.hls_playlist_name = iter->second;
|
||||
descriptor.hls_playlist_name = pair.second;
|
||||
break;
|
||||
}
|
||||
case kHlsIframePlaylistNameField: {
|
||||
descriptor.hls_iframe_playlist_name = iter->second;
|
||||
descriptor.hls_iframe_playlist_name = pair.second;
|
||||
break;
|
||||
}
|
||||
case kTrickPlayFactorField: {
|
||||
unsigned factor;
|
||||
if (!base::StringToUint(iter->second, &factor)) {
|
||||
LOG(ERROR) << "Non-numeric trick play factor " << iter->second
|
||||
if (!absl::SimpleAtoi(pair.second, &factor)) {
|
||||
LOG(ERROR) << "Non-numeric trick play factor " << pair.second
|
||||
<< " specified.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
if (factor == 0) {
|
||||
LOG(ERROR) << "Stream trick_play_factor should be > 0.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
descriptor.trick_play_factor = factor;
|
||||
break;
|
||||
}
|
||||
case kSkipEncryptionField: {
|
||||
unsigned skip_encryption_value;
|
||||
if (!base::StringToUint(iter->second, &skip_encryption_value)) {
|
||||
if (!absl::SimpleAtoi(pair.second, &skip_encryption_value)) {
|
||||
LOG(ERROR) << "Non-numeric option for skip encryption field "
|
||||
"specified (" << iter->second << ").";
|
||||
return base::nullopt;
|
||||
"specified ("
|
||||
<< pair.second << ").";
|
||||
return std::nullopt;
|
||||
}
|
||||
if (skip_encryption_value > 1) {
|
||||
LOG(ERROR) << "skip_encryption should be either 0 or 1.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
descriptor.skip_encryption = skip_encryption_value > 0;
|
||||
break;
|
||||
}
|
||||
case kDrmStreamLabelField:
|
||||
descriptor.drm_label = iter->second;
|
||||
descriptor.drm_label = pair.second;
|
||||
break;
|
||||
case kHlsCharacteristicsField:
|
||||
descriptor.hls_characteristics =
|
||||
base::SplitString(iter->second, ";:", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
SplitAndTrimSkipEmpty(pair.second, ';');
|
||||
break;
|
||||
case kDashAccessiblitiesField:
|
||||
case kDashAccessiblitiesField: {
|
||||
descriptor.dash_accessiblities =
|
||||
base::SplitString(iter->second, ";", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
SplitAndTrimSkipEmpty(pair.second, ';');
|
||||
for (const std::string& accessibility :
|
||||
descriptor.dash_accessiblities) {
|
||||
size_t pos = accessibility.find('=');
|
||||
if (pos == std::string::npos) {
|
||||
LOG(ERROR)
|
||||
<< "Accessibility should be in scheme=value format, but seeing "
|
||||
<< accessibility;
|
||||
return base::nullopt;
|
||||
LOG(ERROR) << "Accessibility should be in scheme=value format, "
|
||||
"but seeing "
|
||||
<< accessibility;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
case kDashRolesField:
|
||||
descriptor.dash_roles =
|
||||
base::SplitString(iter->second, ";", base::TRIM_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY);
|
||||
descriptor.dash_roles = SplitAndTrimSkipEmpty(pair.second, ';');
|
||||
break;
|
||||
case kDashOnlyField:
|
||||
unsigned dash_only_value;
|
||||
if (!base::StringToUint(iter->second, &dash_only_value)) {
|
||||
if (!absl::SimpleAtoi(pair.second, &dash_only_value)) {
|
||||
LOG(ERROR) << "Non-numeric option for dash_only field "
|
||||
"specified (" << iter->second << ").";
|
||||
return base::nullopt;
|
||||
"specified ("
|
||||
<< pair.second << ").";
|
||||
return std::nullopt;
|
||||
}
|
||||
if (dash_only_value > 1) {
|
||||
LOG(ERROR) << "dash_only should be either 0 or 1.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
descriptor.dash_only = dash_only_value > 0;
|
||||
break;
|
||||
case kHlsOnlyField:
|
||||
unsigned hls_only_value;
|
||||
if (!base::StringToUint(iter->second, &hls_only_value)) {
|
||||
if (!absl::SimpleAtoi(pair.second, &hls_only_value)) {
|
||||
LOG(ERROR) << "Non-numeric option for hls_only field "
|
||||
"specified (" << iter->second << ").";
|
||||
return base::nullopt;
|
||||
"specified ("
|
||||
<< pair.second << ").";
|
||||
return std::nullopt;
|
||||
}
|
||||
if (hls_only_value > 1) {
|
||||
LOG(ERROR) << "hls_only should be either 0 or 1.";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
descriptor.hls_only = hls_only_value > 0;
|
||||
break;
|
||||
default:
|
||||
LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first
|
||||
LOG(ERROR) << "Unknown field in stream descriptor (\"" << pair.first
|
||||
<< "\").";
|
||||
return base::nullopt;
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
return descriptor;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "packager/base/optional.h"
|
||||
#include <optional>
|
||||
#include "packager/packager.h"
|
||||
|
||||
namespace shaka {
|
||||
|
@ -21,7 +21,7 @@ namespace shaka {
|
|||
/// @param descriptor_list is a pointer to the sorted descriptor list into
|
||||
/// which the new descriptor should be inserted.
|
||||
/// @return true if successful, false otherwise. May print error messages.
|
||||
base::Optional<StreamDescriptor> ParseStreamDescriptor(
|
||||
std::optional<StreamDescriptor> ParseStreamDescriptor(
|
||||
const std::string& descriptor_string);
|
||||
|
||||
} // namespace shaka
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include <absl/strings/str_format.h>
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
@ -41,13 +41,12 @@ bool ValidateFlag(const char* flag_name,
|
|||
const char* label) {
|
||||
if (flag_value.empty()) {
|
||||
if (!optional && condition) {
|
||||
PrintError(
|
||||
base::StringPrintf("--%s is required if %s.", flag_name, label));
|
||||
PrintError(absl::StrFormat("--%s is required if %s.", flag_name, label));
|
||||
return false;
|
||||
}
|
||||
} else if (!condition) {
|
||||
PrintError(base::StringPrintf(
|
||||
"--%s should be specified only if %s.", flag_name, label));
|
||||
PrintError(absl::StrFormat("--%s should be specified only if %s.",
|
||||
flag_name, label));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
|
||||
#include "packager/app/vlog_flags.h"
|
||||
|
||||
DEFINE_int32(v,
|
||||
0,
|
||||
"Show all VLOG(m) or DVLOG(m) messages for m <= this. "
|
||||
"Overridable by --vmodule.");
|
||||
DEFINE_string(
|
||||
ABSL_FLAG(int32_t,
|
||||
v,
|
||||
0,
|
||||
"Show all VLOG(m) or DVLOG(m) messages for m <= this. "
|
||||
"Overridable by --vmodule.");
|
||||
ABSL_FLAG(
|
||||
std::string,
|
||||
vmodule,
|
||||
"",
|
||||
"Per-module verbose level."
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
#ifndef APP_VLOG_FLAGS_H_
|
||||
#define APP_VLOG_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
DECLARE_int32(v);
|
||||
DECLARE_string(vmodule);
|
||||
// ABSL_DECLARE_FLAG(int32_t, v);
|
||||
// ABSL_DECLARE_FLAG(std::string, vmodule);
|
||||
|
||||
#endif // APP_VLOG_FLAGS_H_
|
||||
|
|
|
@ -8,60 +8,80 @@
|
|||
|
||||
#include "packager/app/widevine_encryption_flags.h"
|
||||
|
||||
#include <absl/flags/flag.h>
|
||||
#include <absl/strings/ascii.h>
|
||||
#include <absl/strings/match.h>
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <glog/logging.h>
|
||||
#include <string_view>
|
||||
#include "packager/app/validate_flag.h"
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_piece.h"
|
||||
#include "packager/base/strings/string_util.h"
|
||||
#include "packager/utils/absl_flag_hexbytes.h"
|
||||
|
||||
DEFINE_bool(enable_widevine_encryption,
|
||||
false,
|
||||
"Enable encryption with Widevine key server. User should provide "
|
||||
"either AES signing key (--aes_signing_key, --aes_signing_iv) or "
|
||||
"RSA signing key (--rsa_signing_key_path).");
|
||||
DEFINE_bool(enable_widevine_decryption,
|
||||
false,
|
||||
"Enable decryption with Widevine license server/proxy. User should "
|
||||
"provide either AES signing key (--aes_signing_key, "
|
||||
"--aes_signing_iv) or RSA signing key (--rsa_signing_key_path).");
|
||||
DEFINE_string(key_server_url, "", "Key server url. Required for encryption and "
|
||||
"decryption");
|
||||
DEFINE_hex_bytes(content_id, "", "Content Id (hex).");
|
||||
DEFINE_string(policy,
|
||||
"",
|
||||
"The name of a stored policy, which specifies DRM content "
|
||||
"rights.");
|
||||
DEFINE_int32(max_sd_pixels,
|
||||
768 * 576,
|
||||
"The video track is considered SD if its max pixels per frame is "
|
||||
"no higher than max_sd_pixels. Default: 442368 (768 x 576).");
|
||||
DEFINE_int32(max_hd_pixels,
|
||||
1920 * 1080,
|
||||
"The video track is considered HD if its max pixels per frame is "
|
||||
"higher than max_sd_pixels, but no higher than max_hd_pixels. "
|
||||
"Default: 2073600 (1920 x 1080).");
|
||||
DEFINE_int32(max_uhd1_pixels,
|
||||
4096 * 2160,
|
||||
"The video track is considered UHD1 if its max pixels per frame "
|
||||
"is higher than max_hd_pixels, but no higher than max_uhd1_pixels."
|
||||
" Otherwise it is UHD2. Default: 8847360 (4096 x 2160).");
|
||||
DEFINE_string(signer, "", "The name of the signer.");
|
||||
DEFINE_hex_bytes(aes_signing_key,
|
||||
"",
|
||||
"AES signing key in hex string. --aes_signing_iv is required. "
|
||||
"Exclusive with --rsa_signing_key_path.");
|
||||
DEFINE_hex_bytes(aes_signing_iv, "", "AES signing iv in hex string.");
|
||||
DEFINE_string(rsa_signing_key_path,
|
||||
"",
|
||||
"Stores PKCS#1 RSA private key for request signing. Exclusive "
|
||||
"with --aes_signing_key.");
|
||||
DEFINE_int32(crypto_period_duration,
|
||||
0,
|
||||
"Crypto period duration in seconds. If it is non-zero, key "
|
||||
"rotation is enabled.");
|
||||
DEFINE_hex_bytes(group_id, "", "Identifier for a group of licenses (hex).");
|
||||
DEFINE_bool(enable_entitlement_license,
|
||||
false,
|
||||
"Enable entitlement license when using Widevine key server.");
|
||||
ABSL_FLAG(bool,
|
||||
enable_widevine_encryption,
|
||||
false,
|
||||
"Enable encryption with Widevine key server. User should provide "
|
||||
"either AES signing key (--aes_signing_key, --aes_signing_iv) or "
|
||||
"RSA signing key (--rsa_signing_key_path).");
|
||||
ABSL_FLAG(bool,
|
||||
enable_widevine_decryption,
|
||||
false,
|
||||
"Enable decryption with Widevine license server/proxy. User should "
|
||||
"provide either AES signing key (--aes_signing_key, "
|
||||
"--aes_signing_iv) or RSA signing key (--rsa_signing_key_path).");
|
||||
ABSL_FLAG(std::string,
|
||||
key_server_url,
|
||||
"",
|
||||
"Key server url. Required for encryption and "
|
||||
"decryption");
|
||||
ABSL_FLAG(shaka::HexBytes, content_id, {}, "Content Id (hex).");
|
||||
ABSL_FLAG(std::string,
|
||||
policy,
|
||||
"",
|
||||
"The name of a stored policy, which specifies DRM content "
|
||||
"rights.");
|
||||
ABSL_FLAG(int32_t,
|
||||
max_sd_pixels,
|
||||
768 * 576,
|
||||
"The video track is considered SD if its max pixels per frame is "
|
||||
"no higher than max_sd_pixels. Default: 442368 (768 x 576).");
|
||||
ABSL_FLAG(int32_t,
|
||||
max_hd_pixels,
|
||||
1920 * 1080,
|
||||
"The video track is considered HD if its max pixels per frame is "
|
||||
"higher than max_sd_pixels, but no higher than max_hd_pixels. "
|
||||
"Default: 2073600 (1920 x 1080).");
|
||||
ABSL_FLAG(int32_t,
|
||||
max_uhd1_pixels,
|
||||
4096 * 2160,
|
||||
"The video track is considered UHD1 if its max pixels per frame "
|
||||
"is higher than max_hd_pixels, but no higher than max_uhd1_pixels."
|
||||
" Otherwise it is UHD2. Default: 8847360 (4096 x 2160).");
|
||||
ABSL_FLAG(std::string, signer, "", "The name of the signer.");
|
||||
ABSL_FLAG(shaka::HexBytes,
|
||||
aes_signing_key,
|
||||
{},
|
||||
"AES signing key in hex string. --aes_signing_iv is required. "
|
||||
"Exclusive with --rsa_signing_key_path.");
|
||||
ABSL_FLAG(shaka::HexBytes, aes_signing_iv, {}, "AES signing iv in hex string.");
|
||||
ABSL_FLAG(std::string,
|
||||
rsa_signing_key_path,
|
||||
"",
|
||||
"Stores PKCS#1 RSA private key for request signing. Exclusive "
|
||||
"with --aes_signing_key.");
|
||||
ABSL_FLAG(int32_t,
|
||||
crypto_period_duration,
|
||||
0,
|
||||
"Crypto period duration in seconds. If it is non-zero, key "
|
||||
"rotation is enabled.");
|
||||
ABSL_FLAG(shaka::HexBytes,
|
||||
group_id,
|
||||
{},
|
||||
"Identifier for a group of licenses (hex).");
|
||||
ABSL_FLAG(bool,
|
||||
enable_entitlement_license,
|
||||
false,
|
||||
"Enable entitlement license when using Widevine key server.");
|
||||
|
||||
namespace shaka {
|
||||
namespace {
|
||||
|
@ -72,28 +92,23 @@ bool ValidateWidevineCryptoFlags() {
|
|||
bool success = true;
|
||||
|
||||
const bool widevine_crypto =
|
||||
FLAGS_enable_widevine_encryption || FLAGS_enable_widevine_decryption;
|
||||
absl::GetFlag(FLAGS_enable_widevine_encryption) ||
|
||||
absl::GetFlag(FLAGS_enable_widevine_decryption);
|
||||
const char widevine_crypto_label[] =
|
||||
"--enable_widevine_encryption/decryption";
|
||||
// key_server_url and signer (optional) are associated with
|
||||
// enable_widevine_encryption and enable_widevine_descryption.
|
||||
if (!ValidateFlag("key_server_url",
|
||||
FLAGS_key_server_url,
|
||||
widevine_crypto,
|
||||
!kOptional,
|
||||
widevine_crypto_label)) {
|
||||
if (!ValidateFlag("key_server_url", absl::GetFlag(FLAGS_key_server_url),
|
||||
widevine_crypto, !kOptional, widevine_crypto_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (!ValidateFlag("signer",
|
||||
FLAGS_signer,
|
||||
widevine_crypto,
|
||||
kOptional,
|
||||
widevine_crypto_label)) {
|
||||
if (!ValidateFlag("signer", absl::GetFlag(FLAGS_signer), widevine_crypto,
|
||||
kOptional, widevine_crypto_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (widevine_crypto && FLAGS_signer.empty() &&
|
||||
base::StartsWith(base::StringPiece(FLAGS_key_server_url), "http",
|
||||
base::CompareCase::INSENSITIVE_ASCII)) {
|
||||
if (widevine_crypto && absl::GetFlag(FLAGS_signer).empty() &&
|
||||
absl::StartsWith(
|
||||
absl::AsciiStrToLower(absl::GetFlag(FLAGS_key_server_url)), "http")) {
|
||||
LOG(WARNING) << "--signer is likely required with "
|
||||
"--enable_widevine_encryption/decryption.";
|
||||
}
|
||||
|
@ -101,57 +116,55 @@ bool ValidateWidevineCryptoFlags() {
|
|||
const char widevine_encryption_label[] = "--enable_widevine_encryption";
|
||||
// content_id and policy (optional) are associated with
|
||||
// enable_widevine_encryption.
|
||||
if (!ValidateFlag("content_id",
|
||||
FLAGS_content_id_bytes,
|
||||
FLAGS_enable_widevine_encryption,
|
||||
!kOptional,
|
||||
if (!ValidateFlag("content_id", absl::GetFlag(FLAGS_content_id).bytes,
|
||||
absl::GetFlag(FLAGS_enable_widevine_encryption), !kOptional,
|
||||
widevine_encryption_label)) {
|
||||
success = false;
|
||||
}
|
||||
if (!ValidateFlag("policy",
|
||||
FLAGS_policy,
|
||||
FLAGS_enable_widevine_encryption,
|
||||
kOptional,
|
||||
if (!ValidateFlag("policy", absl::GetFlag(FLAGS_policy),
|
||||
absl::GetFlag(FLAGS_enable_widevine_encryption), kOptional,
|
||||
widevine_encryption_label)) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
if (FLAGS_max_sd_pixels <= 0) {
|
||||
if (absl::GetFlag(FLAGS_max_sd_pixels) <= 0) {
|
||||
PrintError("--max_sd_pixels must be positive.");
|
||||
success = false;
|
||||
}
|
||||
if (FLAGS_max_hd_pixels <= 0) {
|
||||
if (absl::GetFlag(FLAGS_max_hd_pixels) <= 0) {
|
||||
PrintError("--max_hd_pixels must be positive.");
|
||||
success = false;
|
||||
}
|
||||
if (FLAGS_max_uhd1_pixels <= 0) {
|
||||
if (absl::GetFlag(FLAGS_max_uhd1_pixels) <= 0) {
|
||||
PrintError("--max_uhd1_pixels must be positive.");
|
||||
success = false;
|
||||
}
|
||||
if (FLAGS_max_hd_pixels <= FLAGS_max_sd_pixels) {
|
||||
if (absl::GetFlag(FLAGS_max_hd_pixels) <=
|
||||
absl::GetFlag(FLAGS_max_sd_pixels)) {
|
||||
PrintError("--max_hd_pixels must be greater than --max_sd_pixels.");
|
||||
success = false;
|
||||
}
|
||||
if (FLAGS_max_uhd1_pixels <= FLAGS_max_hd_pixels) {
|
||||
if (absl::GetFlag(FLAGS_max_uhd1_pixels) <=
|
||||
absl::GetFlag(FLAGS_max_hd_pixels)) {
|
||||
PrintError("--max_uhd1_pixels must be greater than --max_hd_pixels.");
|
||||
success = false;
|
||||
}
|
||||
|
||||
const bool aes = !FLAGS_aes_signing_key_bytes.empty() ||
|
||||
!FLAGS_aes_signing_iv_bytes.empty();
|
||||
if (aes && (FLAGS_aes_signing_key_bytes.empty() ||
|
||||
FLAGS_aes_signing_iv_bytes.empty())) {
|
||||
const bool aes = !absl::GetFlag(FLAGS_aes_signing_key).bytes.empty() ||
|
||||
!absl::GetFlag(FLAGS_aes_signing_iv).bytes.empty();
|
||||
if (aes && (absl::GetFlag(FLAGS_aes_signing_key).bytes.empty() ||
|
||||
absl::GetFlag(FLAGS_aes_signing_iv).bytes.empty())) {
|
||||
PrintError("--aes_signing_key/iv is required if using aes signing.");
|
||||
success = false;
|
||||
}
|
||||
|
||||
const bool rsa = !FLAGS_rsa_signing_key_path.empty();
|
||||
const bool rsa = !absl::GetFlag(FLAGS_rsa_signing_key_path).empty();
|
||||
|
||||
if (FLAGS_signer.empty() && (aes || rsa)) {
|
||||
if (absl::GetFlag(FLAGS_signer).empty() && (aes || rsa)) {
|
||||
PrintError("--signer is required if using aes/rsa signing.");
|
||||
success = false;
|
||||
}
|
||||
if (!FLAGS_signer.empty() && !aes && !rsa) {
|
||||
if (!absl::GetFlag(FLAGS_signer).empty() && !aes && !rsa) {
|
||||
PrintError(
|
||||
"--aes_signing_key/iv or --rsa_signing_key_path is required with "
|
||||
"--signer.");
|
||||
|
@ -164,7 +177,7 @@ bool ValidateWidevineCryptoFlags() {
|
|||
success = false;
|
||||
}
|
||||
|
||||
if (FLAGS_crypto_period_duration < 0) {
|
||||
if (absl::GetFlag(FLAGS_crypto_period_duration) < 0) {
|
||||
PrintError("--crypto_period_duration should not be negative.");
|
||||
success = false;
|
||||
}
|
||||
|
|
|
@ -9,25 +9,26 @@
|
|||
#ifndef APP_WIDEVINE_ENCRYPTION_FLAGS_H_
|
||||
#define APP_WIDEVINE_ENCRYPTION_FLAGS_H_
|
||||
|
||||
#include <gflags/gflags.h>
|
||||
#include <absl/flags/declare.h>
|
||||
#include <absl/flags/flag.h>
|
||||
|
||||
#include "packager/app/gflags_hex_bytes.h"
|
||||
#include "packager/utils/absl_flag_hexbytes.h"
|
||||
|
||||
DECLARE_bool(enable_widevine_encryption);
|
||||
DECLARE_bool(enable_widevine_decryption);
|
||||
DECLARE_string(key_server_url);
|
||||
DECLARE_hex_bytes(content_id);
|
||||
DECLARE_string(policy);
|
||||
DECLARE_int32(max_sd_pixels);
|
||||
DECLARE_int32(max_hd_pixels);
|
||||
DECLARE_int32(max_uhd1_pixels);
|
||||
DECLARE_string(signer);
|
||||
DECLARE_hex_bytes(aes_signing_key);
|
||||
DECLARE_hex_bytes(aes_signing_iv);
|
||||
DECLARE_string(rsa_signing_key_path);
|
||||
DECLARE_int32(crypto_period_duration);
|
||||
DECLARE_hex_bytes(group_id);
|
||||
DECLARE_bool(enable_entitlement_license);
|
||||
ABSL_DECLARE_FLAG(bool, enable_widevine_encryption);
|
||||
ABSL_DECLARE_FLAG(bool, enable_widevine_decryption);
|
||||
ABSL_DECLARE_FLAG(std::string, key_server_url);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, content_id);
|
||||
ABSL_DECLARE_FLAG(std::string, policy);
|
||||
ABSL_DECLARE_FLAG(int32_t, max_sd_pixels);
|
||||
ABSL_DECLARE_FLAG(int32_t, max_hd_pixels);
|
||||
ABSL_DECLARE_FLAG(int32_t, max_uhd1_pixels);
|
||||
ABSL_DECLARE_FLAG(std::string, signer);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, aes_signing_key);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, aes_signing_iv);
|
||||
ABSL_DECLARE_FLAG(std::string, rsa_signing_key_path);
|
||||
ABSL_DECLARE_FLAG(int32_t, crypto_period_duration);
|
||||
ABSL_DECLARE_FLAG(shaka::HexBytes, group_id);
|
||||
ABSL_DECLARE_FLAG(bool, enable_entitlement_license);
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
|
|
@ -29,6 +29,10 @@ target_link_libraries(file
|
|||
status
|
||||
version)
|
||||
|
||||
if(LIBPACKAGER_SHARED)
|
||||
target_compile_definitions(file PUBLIC SHAKA_IMPLEMENTATION)
|
||||
endif()
|
||||
|
||||
add_library(file_test_util STATIC
|
||||
file_test_util.cc)
|
||||
target_link_libraries(file_test_util
|
||||
|
|
|
@ -42,4 +42,27 @@
|
|||
#define DVLOG_IF(verboselevel, condition) \
|
||||
static_cast<void>(0), !(condition) ? (void)0 : VLOG(verboselevel)
|
||||
|
||||
#if defined(SHARED_LIBRARY_BUILD)
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(SHAKA_IMPLEMENTATION)
|
||||
#define SHAKA_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define SHAKA_EXPORT __declspec(dllimport)
|
||||
#endif // defined(SHAKA_IMPLEMENTATION)
|
||||
|
||||
#else // defined(_WIN32)
|
||||
|
||||
#if defined(SHAKA_IMPLEMENTATION)
|
||||
#define SHAKA_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define SHAKA_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#else // defined(SHARED_LIBRARY_BUILD)
|
||||
#define SHAKA_EXPORT
|
||||
#endif // defined(SHARED_LIBRARY_BUILD)
|
||||
|
||||
#endif // PACKAGER_MACROS_H_
|
||||
|
|
|
@ -15,3 +15,4 @@ add_subdirectory(origin)
|
|||
add_subdirectory(replicator)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(trick_play)
|
||||
add_subdirectory(demuxer)
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright 2017 Google LLC. All rights reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
add_library(demuxer STATIC
|
||||
demuxer.cc
|
||||
demuxer.h)
|
||||
target_link_libraries(demuxer
|
||||
media_base
|
||||
mp2t
|
||||
mp4
|
||||
webvtt
|
||||
wvm
|
||||
formats_webm
|
||||
media_origin)
|
||||
|
||||
add_executable(demuxer_unittest
|
||||
demuxer_unittest.cc
|
||||
)
|
||||
target_link_libraries(demuxer_unittest
|
||||
demuxer
|
||||
file
|
||||
file_test_util
|
||||
test_data_util
|
||||
absl::flags
|
||||
media_event
|
||||
media_handler_test_base
|
||||
mock_muxer_listener
|
||||
gmock
|
||||
gtest
|
||||
gtest_main
|
||||
)
|
||||
|
||||
add_test(NAME demuxer_unittest COMMAND demuxer_unittest)
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "packager/base/bind.h"
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include <absl/strings/escaping.h>
|
||||
#include <absl/strings/numbers.h>
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <glog/logging.h>
|
||||
#include <functional>
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/media/base/decryptor_source.h"
|
||||
#include "packager/media/base/key_source.h"
|
||||
|
@ -45,7 +47,7 @@ std::string GetStreamLabel(size_t stream_index) {
|
|||
case kBaseTextOutputStreamIndex:
|
||||
return "text";
|
||||
default:
|
||||
return base::SizeTToString(stream_index);
|
||||
return absl::StrFormat("%u", stream_index);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +61,7 @@ bool GetStreamIndex(const std::string& stream_label, size_t* stream_index) {
|
|||
*stream_index = kBaseTextOutputStreamIndex;
|
||||
} else {
|
||||
// Expect stream_label to be a zero based stream id.
|
||||
if (!base::StringToSizeT(stream_label, stream_index)) {
|
||||
if (!absl::SimpleAtoi(stream_label, stream_index)) {
|
||||
LOG(ERROR) << "Invalid argument --stream=" << stream_label << "; "
|
||||
<< "should be 'audio', 'video', 'text', or a number";
|
||||
return false;
|
||||
|
@ -203,8 +205,9 @@ Status Demuxer::InitializeParser() {
|
|||
case CONTAINER_UNKNOWN: {
|
||||
const int64_t kDumpSizeLimit = 512;
|
||||
LOG(ERROR) << "Failed to detect the container type from the buffer: "
|
||||
<< base::HexEncode(buffer_.get(),
|
||||
std::min(bytes_read, kDumpSizeLimit));
|
||||
<< absl::BytesToHexString(absl::string_view(
|
||||
reinterpret_cast<const char*>(buffer_.get()),
|
||||
std::min(bytes_read, kDumpSizeLimit)));
|
||||
return Status(error::INVALID_ARGUMENT,
|
||||
"Failed to detect the container type.");
|
||||
}
|
||||
|
@ -215,9 +218,11 @@ Status Demuxer::InitializeParser() {
|
|||
}
|
||||
|
||||
parser_->Init(
|
||||
base::Bind(&Demuxer::ParserInitEvent, base::Unretained(this)),
|
||||
base::Bind(&Demuxer::NewMediaSampleEvent, base::Unretained(this)),
|
||||
base::Bind(&Demuxer::NewTextSampleEvent, base::Unretained(this)),
|
||||
std::bind(&Demuxer::ParserInitEvent, this, std::placeholders::_1),
|
||||
std::bind(&Demuxer::NewMediaSampleEvent, this, std::placeholders::_1,
|
||||
std::placeholders::_2),
|
||||
std::bind(&Demuxer::NewTextSampleEvent, this, std::placeholders::_1,
|
||||
std::placeholders::_2),
|
||||
key_source_.get());
|
||||
|
||||
// Handle trailing 'moov'.
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
# Copyright 2017 Google LLC. All rights reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'shaka_code': 1,
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'demuxer',
|
||||
'type': '<(component)',
|
||||
'sources': [
|
||||
'demuxer.cc',
|
||||
'demuxer.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'../base/media_base.gyp:media_base',
|
||||
'../formats/mp2t/mp2t.gyp:mp2t',
|
||||
'../formats/mp4/mp4.gyp:mp4',
|
||||
'../formats/webm/webm.gyp:webm',
|
||||
'../formats/webvtt/webvtt.gyp:webvtt',
|
||||
'../formats/wvm/wvm.gyp:wvm',
|
||||
'../origin/origin.gyp:origin',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'demuxer_unittest',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'demuxer_unittest.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'../../testing/gmock.gyp:gmock',
|
||||
'../../testing/gtest.gyp:gtest',
|
||||
'../base/media_base.gyp:media_handler_test_base',
|
||||
'../test/media_test.gyp:media_test_support',
|
||||
'demuxer',
|
||||
]
|
||||
},
|
||||
],
|
||||
}
|
|
@ -11,10 +11,10 @@
|
|||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "packager/base/compiler_specific.h"
|
||||
#include "packager/macros.h"
|
||||
#include "packager/media/base/container_names.h"
|
||||
#include "packager/media/origin/origin_handler.h"
|
||||
#include "packager/status.h"
|
||||
#include "packager/status/status.h"
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
|
|
@ -12,13 +12,14 @@
|
|||
#include "packager/media/base/media_handler_test_base.h"
|
||||
#include "packager/media/base/raw_key_source.h"
|
||||
#include "packager/media/test/test_data_util.h"
|
||||
#include "packager/status_test_util.h"
|
||||
#include "packager/status/status_test_util.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
namespace {
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::DoAll;
|
||||
using ::testing::Return;
|
||||
using ::testing::SetArgPointee;
|
||||
|
||||
|
@ -53,8 +54,8 @@ TEST_F(DemuxerTest, FileNotFound) {
|
|||
}
|
||||
|
||||
TEST_F(DemuxerTest, EncryptedContentWithoutKeySource) {
|
||||
Demuxer demuxer(GetAppTestDataFilePath("encryption/bear-640x360-video.mp4")
|
||||
.AsUTF8Unsafe());
|
||||
Demuxer demuxer(
|
||||
GetAppTestDataFilePath("encryption/bear-640x360-video.mp4").string());
|
||||
ASSERT_OK(demuxer.SetHandler("video", some_handler()));
|
||||
EXPECT_EQ(error::INVALID_ARGUMENT, demuxer.Run().error_code());
|
||||
}
|
||||
|
@ -65,8 +66,8 @@ TEST_F(DemuxerTest, EncryptedContentWithKeySource) {
|
|||
.WillOnce(
|
||||
DoAll(SetArgPointee<1>(GetMockEncryptionKey()), Return(Status::OK)));
|
||||
|
||||
Demuxer demuxer(GetAppTestDataFilePath("encryption/bear-640x360-video.mp4")
|
||||
.AsUTF8Unsafe());
|
||||
Demuxer demuxer(
|
||||
GetAppTestDataFilePath("encryption/bear-640x360-video.mp4").string());
|
||||
demuxer.SetKeySource(std::move(mock_key_source));
|
||||
ASSERT_OK(demuxer.SetHandler("video", some_handler()));
|
||||
EXPECT_OK(demuxer.Run());
|
||||
|
|
|
@ -24,6 +24,7 @@ target_link_libraries(webvtt
|
|||
media_base
|
||||
mp4
|
||||
media_origin
|
||||
string_utils
|
||||
)
|
||||
|
||||
add_executable(webvtt_unittest
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "packager/kv_pairs/kv_pairs.h"
|
||||
#include "packager/media/base/text_stream_info.h"
|
||||
#include "packager/media/formats/webvtt/webvtt_utils.h"
|
||||
#include "packager/utils/string_trim_split.h"
|
||||
|
||||
namespace shaka {
|
||||
namespace media {
|
||||
|
@ -91,19 +92,7 @@ bool ParsePercent(const std::string& str, float* value) {
|
|||
}
|
||||
|
||||
bool ParseDoublePercent(const std::string& str, float* a, float* b) {
|
||||
// Split the string by ','
|
||||
std::vector<absl::string_view> tokens =
|
||||
absl::StrSplit(str, ',', absl::SkipEmpty());
|
||||
|
||||
// Trim whitespace from each result and skip any empty ones
|
||||
std::vector<std::string> percents;
|
||||
for (const absl::string_view& token : tokens) {
|
||||
std::string trimmed = std::string(token);
|
||||
absl::StripAsciiWhitespace(&trimmed);
|
||||
if (!trimmed.empty()) {
|
||||
percents.push_back(trimmed);
|
||||
}
|
||||
}
|
||||
std::vector<std::string> percents = SplitAndTrimSkipEmpty(str, ',');
|
||||
|
||||
if (percents.size() != 2) {
|
||||
return false;
|
||||
|
@ -400,19 +389,8 @@ bool WebVttParser::ParseCueWithId(const std::vector<std::string>& block) {
|
|||
bool WebVttParser::ParseCue(const std::string& id,
|
||||
const std::string* block,
|
||||
size_t block_size) {
|
||||
// Split the string by ','
|
||||
std::vector<absl::string_view> tokens =
|
||||
absl::StrSplit(block[0], ' ', absl::SkipEmpty());
|
||||
|
||||
// Trim whitespace from each result and skip any empty ones
|
||||
std::vector<std::string> time_and_style;
|
||||
for (const absl::string_view& token : tokens) {
|
||||
std::string trimmed = std::string(token);
|
||||
absl::StripAsciiWhitespace(&trimmed);
|
||||
if (!trimmed.empty()) {
|
||||
time_and_style.push_back(trimmed);
|
||||
}
|
||||
}
|
||||
std::vector<std::string> time_and_style =
|
||||
SplitAndTrimSkipEmpty(block[0], ' ');
|
||||
|
||||
int64_t start_time = 0;
|
||||
int64_t end_time = 0;
|
||||
|
|
|
@ -18,8 +18,8 @@ std::filesystem::path GetTestDataFilePath(const std::string& name) {
|
|||
// Returns a file path for a file in the media/app/test/testdata directory.
|
||||
std::filesystem::path GetAppTestDataFilePath(const std::string& name) {
|
||||
auto data_dir = std::filesystem::u8path(TEST_DATA_DIR);
|
||||
auto app_data_dir =
|
||||
data_dir.parent_path().parent_path() / "app" / "test" / "testdata";
|
||||
auto app_data_dir = data_dir.parent_path().parent_path().parent_path() /
|
||||
"app" / "test" / "testdata";
|
||||
return app_data_dir / name;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,21 +8,17 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <absl/strings/str_format.h>
|
||||
#include <glog/logging.h>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include "absl/strings/match.h"
|
||||
#include "packager/app/job_manager.h"
|
||||
#include "packager/app/libcrypto_threading.h"
|
||||
#include "packager/app/muxer_factory.h"
|
||||
#include "packager/app/packager_util.h"
|
||||
#include "packager/app/single_thread_job_manager.h"
|
||||
#include "packager/app/stream_descriptor.h"
|
||||
#include "packager/base/at_exit.h"
|
||||
#include "packager/base/files/file_path.h"
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/optional.h"
|
||||
#include "packager/base/path_service.h"
|
||||
#include "packager/base/strings/string_util.h"
|
||||
#include "packager/base/strings/stringprintf.h"
|
||||
#include "packager/base/threading/simple_thread.h"
|
||||
#include "packager/base/time/clock.h"
|
||||
#include "packager/file/file.h"
|
||||
#include "packager/hls/base/hls_notifier.h"
|
||||
#include "packager/hls/base/simple_hls_notifier.h"
|
||||
|
@ -49,7 +45,7 @@
|
|||
#include "packager/mpd/base/media_info.pb.h"
|
||||
#include "packager/mpd/base/mpd_builder.h"
|
||||
#include "packager/mpd/base/simple_mpd_notifier.h"
|
||||
#include "packager/status_macros.h"
|
||||
#include "packager/status/status_macros.h"
|
||||
#include "packager/version/version.h"
|
||||
|
||||
namespace shaka {
|
||||
|
@ -129,8 +125,8 @@ MediaContainerName GetOutputFormat(const StreamDescriptor& descriptor) {
|
|||
return format;
|
||||
}
|
||||
|
||||
base::Optional<MediaContainerName> format_from_output;
|
||||
base::Optional<MediaContainerName> format_from_segment;
|
||||
std::optional<MediaContainerName> format_from_output;
|
||||
std::optional<MediaContainerName> format_from_segment;
|
||||
if (!descriptor.output.empty()) {
|
||||
format_from_output = DetermineContainerFromFileName(descriptor.output);
|
||||
if (format_from_output.value() == CONTAINER_UNKNOWN) {
|
||||
|
@ -169,12 +165,10 @@ MediaContainerName GetTextOutputCodec(const StreamDescriptor& descriptor) {
|
|||
return output_container;
|
||||
|
||||
const auto input_container = DetermineContainerFromFileName(descriptor.input);
|
||||
if (base::EqualsCaseInsensitiveASCII(descriptor.output_format, "vtt+mp4") ||
|
||||
base::EqualsCaseInsensitiveASCII(descriptor.output_format,
|
||||
"webvtt+mp4")) {
|
||||
if (absl::AsciiStrToLower(descriptor.output_format) == "vtt+mp4" ||
|
||||
absl::AsciiStrToLower(descriptor.output_format) == "webvtt+mp4") {
|
||||
return CONTAINER_WEBVTT;
|
||||
} else if (!base::EqualsCaseInsensitiveASCII(descriptor.output_format,
|
||||
"ttml+mp4") &&
|
||||
} else if (absl::AsciiStrToLower(descriptor.output_format) != "ttml+mp4" &&
|
||||
input_container == CONTAINER_WEBVTT) {
|
||||
// With WebVTT input, default to WebVTT output.
|
||||
return CONTAINER_WEBVTT;
|
||||
|
@ -187,9 +181,9 @@ MediaContainerName GetTextOutputCodec(const StreamDescriptor& descriptor) {
|
|||
bool IsTextStream(const StreamDescriptor& stream) {
|
||||
if (stream.stream_selector == "text")
|
||||
return true;
|
||||
if (base::EqualsCaseInsensitiveASCII(stream.output_format, "vtt+mp4") ||
|
||||
base::EqualsCaseInsensitiveASCII(stream.output_format, "webvtt+mp4") ||
|
||||
base::EqualsCaseInsensitiveASCII(stream.output_format, "ttml+mp4")) {
|
||||
if (absl::AsciiStrToLower(stream.output_format) == "vtt+mp4" ||
|
||||
absl::AsciiStrToLower(stream.output_format) == "webvtt+mp4" ||
|
||||
absl::AsciiStrToLower(stream.output_format) == "ttml+mp4") {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -321,8 +315,7 @@ Status ValidateParams(const PackagingParams& packaging_params,
|
|||
RETURN_IF_ERROR(ValidateStreamDescriptor(
|
||||
packaging_params.test_params.dump_stream_info, descriptor));
|
||||
|
||||
if (base::StartsWith(descriptor.input, "udp://",
|
||||
base::CompareCase::SENSITIVE)) {
|
||||
if (absl::StartsWith(descriptor.input, "udp://")) {
|
||||
const HlsParams& hls_params = packaging_params.hls_params;
|
||||
if (!hls_params.master_playlist_output.empty() &&
|
||||
hls_params.playlist_type == HlsPlaylistType::kVod) {
|
||||
|
@ -419,9 +412,11 @@ bool StreamDescriptorCompareFn(const StreamDescriptor& a,
|
|||
|
||||
// A fake clock that always return time 0 (epoch). Should only be used for
|
||||
// testing.
|
||||
class FakeClock : public base::Clock {
|
||||
class FakeClock : public Clock {
|
||||
public:
|
||||
base::Time Now() override { return base::Time(); }
|
||||
time_point now() noexcept override {
|
||||
return std::chrono::system_clock::time_point(std::chrono::seconds(0));
|
||||
}
|
||||
};
|
||||
|
||||
bool StreamInfoToTextMediaInfo(const StreamDescriptor& stream_descriptor,
|
||||
|
@ -568,7 +563,7 @@ Status CreateTtmlJobs(
|
|||
if (!stream.output.empty()) {
|
||||
if (!File::Copy(stream.input.c_str(), stream.output.c_str())) {
|
||||
std::string error;
|
||||
base::StringAppendF(
|
||||
absl::StrAppendFormat(
|
||||
&error, "Failed to copy the input file (%s) to output file (%s).",
|
||||
stream.input.c_str(), stream.output.c_str());
|
||||
return Status(error::FILE_FAILURE, error);
|
||||
|
@ -833,10 +828,6 @@ Packager::~Packager() {}
|
|||
Status Packager::Initialize(
|
||||
const PackagingParams& packaging_params,
|
||||
const std::vector<StreamDescriptor>& stream_descriptors) {
|
||||
// Needed by base::WorkedPool used in ThreadedIoFile.
|
||||
static base::AtExitManager exit;
|
||||
static media::LibcryptoThreading libcrypto_threading;
|
||||
|
||||
if (internal_)
|
||||
return Status(error::INVALID_ARGUMENT, "Already initialized.");
|
||||
|
||||
|
|
|
@ -1,243 +0,0 @@
|
|||
# Copyright 2014 Google LLC. All rights reserved.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file or at
|
||||
# https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
{
|
||||
'variables': {
|
||||
'shaka_code': 1,
|
||||
},
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'libpackager',
|
||||
'type': '<(libpackager_type)',
|
||||
'sources': [
|
||||
# TODO(kqyang): Clean up the file path.
|
||||
'app/job_manager.cc',
|
||||
'app/job_manager.h',
|
||||
'app/muxer_factory.cc',
|
||||
'app/muxer_factory.h',
|
||||
'app/libcrypto_threading.cc',
|
||||
'app/libcrypto_threading.h',
|
||||
'app/packager_util.cc',
|
||||
'app/packager_util.h',
|
||||
'app/single_thread_job_manager.cc',
|
||||
'app/single_thread_job_manager.h',
|
||||
'packager.cc',
|
||||
'packager.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'file/file.gyp:file',
|
||||
'hls/hls.gyp:hls_builder',
|
||||
'media/chunking/chunking.gyp:chunking',
|
||||
'media/codecs/codecs.gyp:codecs',
|
||||
'media/crypto/crypto.gyp:crypto',
|
||||
'media/demuxer/demuxer.gyp:demuxer',
|
||||
'media/event/media_event.gyp:media_event',
|
||||
'media/formats/dvb/dvb.gyp:dvb',
|
||||
'media/formats/mp2t/mp2t.gyp:mp2t',
|
||||
'media/formats/mp4/mp4.gyp:mp4',
|
||||
'media/formats/packed_audio/packed_audio.gyp:packed_audio',
|
||||
'media/formats/ttml/ttml.gyp:ttml',
|
||||
'media/formats/webm/webm.gyp:webm',
|
||||
'media/formats/webvtt/webvtt.gyp:webvtt',
|
||||
'media/formats/wvm/wvm.gyp:wvm',
|
||||
'media/public/public.gyp:public',
|
||||
'media/replicator/replicator.gyp:replicator',
|
||||
'media/trick_play/trick_play.gyp:trick_play',
|
||||
'mpd/mpd.gyp:mpd_builder',
|
||||
'third_party/boringssl/boringssl.gyp:boringssl',
|
||||
'version/version.gyp:version',
|
||||
],
|
||||
'conditions': [
|
||||
['libpackager_type == "shared_library"', {
|
||||
'defines': [
|
||||
'SHARED_LIBRARY_BUILD',
|
||||
'SHAKA_IMPLEMENTATION',
|
||||
],
|
||||
}],
|
||||
['libpackager_type == "static_library"', {
|
||||
'standalone_static_library': 1,
|
||||
}],
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'packager',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'app/ad_cue_generator_flags.cc',
|
||||
'app/ad_cue_generator_flags.h',
|
||||
'app/crypto_flags.cc',
|
||||
'app/crypto_flags.h',
|
||||
'app/gflags_hex_bytes.cc',
|
||||
'app/gflags_hex_bytes.h',
|
||||
'app/hls_flags.cc',
|
||||
'app/hls_flags.h',
|
||||
'app/manifest_flags.cc',
|
||||
'app/manifest_flags.h',
|
||||
'app/mpd_flags.cc',
|
||||
'app/mpd_flags.h',
|
||||
'app/muxer_flags.cc',
|
||||
'app/muxer_flags.h',
|
||||
'app/packager_main.cc',
|
||||
'app/playready_key_encryption_flags.cc',
|
||||
'app/playready_key_encryption_flags.h',
|
||||
'app/raw_key_encryption_flags.cc',
|
||||
'app/raw_key_encryption_flags.h',
|
||||
'app/protection_system_flags.cc',
|
||||
'app/protection_system_flags.h',
|
||||
'app/retired_flags.cc',
|
||||
'app/retired_flags.h',
|
||||
'app/stream_descriptor.cc',
|
||||
'app/stream_descriptor.h',
|
||||
'app/validate_flag.cc',
|
||||
'app/validate_flag.h',
|
||||
'app/vlog_flags.cc',
|
||||
'app/vlog_flags.h',
|
||||
'app/widevine_encryption_flags.cc',
|
||||
'app/widevine_encryption_flags.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'base/base.gyp:base',
|
||||
'libpackager',
|
||||
'third_party/gflags/gflags.gyp:gflags',
|
||||
'tools/license_notice.gyp:license_notice',
|
||||
],
|
||||
'conditions': [
|
||||
['libpackager_type == "shared_library"', {
|
||||
'defines': [
|
||||
'SHARED_LIBRARY_BUILD',
|
||||
],
|
||||
}],
|
||||
['profiling==1', {
|
||||
'dependencies': [
|
||||
'base/allocator/allocator.gyp:allocator',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'mpd_generator',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'app/mpd_generator.cc',
|
||||
'app/mpd_generator_flags.h',
|
||||
'app/vlog_flags.cc',
|
||||
'app/vlog_flags.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'base/base.gyp:base',
|
||||
'mpd/mpd.gyp:mpd_util',
|
||||
'third_party/gflags/gflags.gyp:gflags',
|
||||
'tools/license_notice.gyp:license_notice',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'packager_test',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'packager_test.cc',
|
||||
],
|
||||
'conditions': [
|
||||
['libpackager_type == "shared_library"', {
|
||||
'defines': [
|
||||
'SHARED_LIBRARY_BUILD',
|
||||
],
|
||||
}],
|
||||
],
|
||||
'dependencies': [
|
||||
'libpackager',
|
||||
'testing/gmock.gyp:gmock',
|
||||
'testing/gtest.gyp:gtest',
|
||||
'testing/gtest.gyp:gtest_main',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'packager_test_py_copy',
|
||||
'type': 'none',
|
||||
'copies': [{
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': [
|
||||
'app/test/packager_app.py',
|
||||
'app/test/packager_test.py',
|
||||
'app/test/test_env.py',
|
||||
],
|
||||
}],
|
||||
'dependencies': ['packager'],
|
||||
},
|
||||
{
|
||||
'target_name': 'pssh_box_py',
|
||||
'type': 'none',
|
||||
'copies': [{
|
||||
'destination': '<(PRODUCT_DIR)',
|
||||
'files': [
|
||||
'tools/pssh/pssh-box.py',
|
||||
],
|
||||
}],
|
||||
'dependencies': [
|
||||
'media/base/media_base.gyp:widevine_pssh_data_proto',
|
||||
'third_party/protobuf/protobuf.gyp:py_proto',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'status',
|
||||
'type': '<(component)',
|
||||
'sources': [
|
||||
'status.cc',
|
||||
'status.h',
|
||||
'status_macros.h',
|
||||
],
|
||||
'dependencies': [
|
||||
'base/base.gyp:base',
|
||||
],
|
||||
'conditions': [
|
||||
['libpackager_type == "shared_library"', {
|
||||
'defines': [
|
||||
'SHARED_LIBRARY_BUILD',
|
||||
'SHAKA_IMPLEMENTATION',
|
||||
],
|
||||
}],
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'status_unittest',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'status_unittest.cc',
|
||||
],
|
||||
'dependencies': [
|
||||
'status',
|
||||
'testing/gmock.gyp:gmock',
|
||||
'testing/gtest.gyp:gtest',
|
||||
'testing/gtest.gyp:gtest_main',
|
||||
]
|
||||
},
|
||||
{
|
||||
'target_name': 'packager_builder_tests',
|
||||
'type': 'none',
|
||||
'dependencies': [
|
||||
'file/file.gyp:file_unittest',
|
||||
'hls/hls.gyp:hls_unittest',
|
||||
'media/base/media_base.gyp:media_base_unittest',
|
||||
'media/chunking/chunking.gyp:chunking_unittest',
|
||||
'media/codecs/codecs.gyp:codecs_unittest',
|
||||
'media/crypto/crypto.gyp:crypto_unittest',
|
||||
'media/demuxer/demuxer.gyp:demuxer_unittest',
|
||||
'media/event/media_event.gyp:media_event_unittest',
|
||||
'media/formats/dvb/dvb.gyp:dvb_unittest',
|
||||
'media/formats/mp2t/mp2t.gyp:mp2t_unittest',
|
||||
'media/formats/mp4/mp4.gyp:mp4_unittest',
|
||||
'media/formats/packed_audio/packed_audio.gyp:packed_audio_unittest',
|
||||
'media/formats/ttml/ttml.gyp:ttml_unittest',
|
||||
'media/formats/webm/webm.gyp:webm_unittest',
|
||||
'media/formats/webvtt/webvtt.gyp:webvtt_unittest',
|
||||
'media/formats/wvm/wvm.gyp:wvm_unittest',
|
||||
'media/trick_play/trick_play.gyp:trick_play_unittest',
|
||||
'mpd/mpd.gyp:mpd_unittest',
|
||||
'packager_test',
|
||||
'status_unittest',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
|
@ -13,12 +13,13 @@
|
|||
|
||||
#include "packager/file/public/buffer_callback_params.h"
|
||||
#include "packager/hls/public/hls_params.h"
|
||||
#include "packager/macros.h"
|
||||
#include "packager/media/public/ad_cue_generator_params.h"
|
||||
#include "packager/media/public/chunking_params.h"
|
||||
#include "packager/media/public/crypto_params.h"
|
||||
#include "packager/media/public/mp4_output_params.h"
|
||||
#include "packager/mpd/public/mpd_params.h"
|
||||
#include "packager/status.h"
|
||||
#include "packager/status/status.h"
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
|
|
@ -10,28 +10,7 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#if defined(SHARED_LIBRARY_BUILD)
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(SHAKA_IMPLEMENTATION)
|
||||
#define SHAKA_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define SHAKA_EXPORT __declspec(dllimport)
|
||||
#endif // defined(SHAKA_IMPLEMENTATION)
|
||||
|
||||
#else // defined(_WIN32)
|
||||
|
||||
#if defined(SHAKA_IMPLEMENTATION)
|
||||
#define SHAKA_EXPORT __attribute__((visibility("default")))
|
||||
#else
|
||||
#define SHAKA_EXPORT
|
||||
#endif
|
||||
|
||||
#endif // defined(_WIN32)
|
||||
|
||||
#else // defined(SHARED_LIBRARY_BUILD)
|
||||
#define SHAKA_EXPORT
|
||||
#endif // defined(SHARED_LIBRARY_BUILD)
|
||||
#include "packager/macros.h"
|
||||
|
||||
namespace shaka {
|
||||
|
||||
|
@ -153,7 +132,7 @@ class SHAKA_EXPORT Status {
|
|||
// generated copy constructor and assignment operator.
|
||||
};
|
||||
|
||||
SHAKA_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x);
|
||||
std::ostream& operator<<(std::ostream& os, const Status& x);
|
||||
|
||||
} // namespace shaka
|
||||
|
||||
|
|
|
@ -27,4 +27,11 @@ add_library(hex_bytes_flags STATIC
|
|||
target_link_libraries(hex_bytes_flags
|
||||
hex_parser
|
||||
absl::strings
|
||||
absl::flags)
|
||||
absl::flags)
|
||||
|
||||
add_library(string_utils
|
||||
string_trim_split.cc
|
||||
)
|
||||
target_link_libraries(string_utils
|
||||
absl::strings
|
||||
)
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2023 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "string_trim_split.h"
|
||||
#include <absl/strings/str_split.h>
|
||||
|
||||
namespace shaka {
|
||||
std::vector<std::string> SplitAndTrimSkipEmpty(const std::string& str,
|
||||
char delimiter) {
|
||||
auto tokens =
|
||||
absl::StrSplit(absl::AsciiStrToLower(str), delimiter, absl::SkipEmpty());
|
||||
std::vector<std::string> results;
|
||||
for (const absl::string_view& token : tokens) {
|
||||
std::string trimmed = std::string(token);
|
||||
absl::StripAsciiWhitespace(&trimmed);
|
||||
if (!trimmed.empty()) {
|
||||
results.push_back(trimmed);
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
} // namespace shaka
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2023 Google LLC. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef SHAKA_PACKAGER_STRING_TRIM_SPLIT_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace shaka {
|
||||
std::vector<std::string> SplitAndTrimSkipEmpty(const std::string& str,
|
||||
char delimiter);
|
||||
}
|
||||
|
||||
#define SHAKA_PACKAGER_STRING_TRIM_SPLIT_H
|
||||
|
||||
#endif // SHAKA_PACKAGER_STRING_TRIM_SPLIT_H
|
Loading…
Reference in New Issue