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:
Cosmin Stejerean 2023-09-08 17:44:17 -07:00 committed by GitHub
parent 274c885253
commit 6b68c138cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 1249 additions and 1296 deletions

View File

@ -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)

View File

@ -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.");

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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_

View File

@ -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.");

View File

@ -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_

View File

@ -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)

View File

@ -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

View File

@ -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_

View File

@ -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.");

View File

@ -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_

View File

@ -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, "

View File

@ -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_

View File

@ -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();
}

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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.");

View File

@ -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_

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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 {

View File

@ -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 "

View File

@ -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_

View File

@ -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;

View File

@ -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 {

View File

@ -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

View File

@ -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();
}

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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."

View File

@ -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_

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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_

View File

@ -15,3 +15,4 @@ add_subdirectory(origin)
add_subdirectory(replicator)
add_subdirectory(test)
add_subdirectory(trick_play)
add_subdirectory(demuxer)

View File

@ -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)

View File

@ -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'.

View File

@ -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',
]
},
],
}

View File

@ -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 {

View File

@ -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());

View File

@ -24,6 +24,7 @@ target_link_libraries(webvtt
media_base
mp4
media_origin
string_utils
)
add_executable(webvtt_unittest

View File

@ -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;

View File

@ -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;
}

View File

@ -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.");

View File

@ -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',
],
},
],
}

View File

@ -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 {

View File

@ -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

View File

@ -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
)

View File

@ -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

View File

@ -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