Add a stream descriptor field for language.
If a stream has no language metadata, or has the wrong metadata, this field allows the user to override this on the command-line. This also maps all specified languages on the command-line to ISO-639-2 tags as required by the MP4 muxer, so that ISO-639-1 tags specified on the command-line do not cause a DCHECK to fail. b/18613148 Change-Id: I473baeecbb3d388db5e06d080179ec6a332b4794
This commit is contained in:
parent
77ec23afe4
commit
3cc86c62b5
|
@ -48,7 +48,10 @@ const char kUsage[] =
|
|||
" - bandwidth (bw): Optional value which contains a user-specified "
|
||||
"content bit rate for the stream, in bits/sec. If specified, this value is "
|
||||
"propagated to the $Bandwidth$ template parameter for segment names. "
|
||||
"If not specified, its value may be estimated.\n";
|
||||
"If not specified, its value may be estimated.\n"
|
||||
" - language (lang): Optional value which contains a user-specified "
|
||||
"language tag. If specified, this value overrides any language metadata "
|
||||
"in the input track.\n";
|
||||
|
||||
enum ExitStatus {
|
||||
kSuccess = 0,
|
||||
|
@ -161,11 +164,11 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
|||
scoped_ptr<MuxerListener> muxer_listener;
|
||||
DCHECK(!(FLAGS_output_media_info && mpd_notifier));
|
||||
if (FLAGS_output_media_info) {
|
||||
const std::string output_mpd_file_name =
|
||||
const std::string output_media_info_file_name =
|
||||
stream_muxer_options.output_file_name + ".media_info";
|
||||
scoped_ptr<VodMediaInfoDumpMuxerListener>
|
||||
vod_media_info_dump_muxer_listener(
|
||||
new VodMediaInfoDumpMuxerListener(output_mpd_file_name));
|
||||
new VodMediaInfoDumpMuxerListener(output_media_info_file_name));
|
||||
vod_media_info_dump_muxer_listener->SetContentProtectionSchemeIdUri(
|
||||
FLAGS_scheme_id_uri);
|
||||
muxer_listener = vod_media_info_dump_muxer_listener.Pass();
|
||||
|
@ -185,6 +188,7 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
|||
|
||||
if (!AddStreamToMuxer(remux_jobs->back()->demuxer()->streams(),
|
||||
stream_iter->stream_selector,
|
||||
stream_iter->language,
|
||||
muxer.get()))
|
||||
return false;
|
||||
remux_jobs->back()->AddMuxer(muxer.Pass());
|
||||
|
|
|
@ -179,6 +179,7 @@ MediaStream* FindFirstAudioStream(const std::vector<MediaStream*>& streams) {
|
|||
|
||||
bool AddStreamToMuxer(const std::vector<MediaStream*>& streams,
|
||||
const std::string& stream_selector,
|
||||
const std::string& language_override,
|
||||
Muxer* muxer) {
|
||||
DCHECK(muxer);
|
||||
|
||||
|
@ -207,6 +208,11 @@ bool AddStreamToMuxer(const std::vector<MediaStream*>& streams,
|
|||
LOG(ERROR) << "No " << stream_selector << " stream found in the input.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!language_override.empty()) {
|
||||
stream->info()->set_language(language_override);
|
||||
}
|
||||
|
||||
muxer->AddStream(stream);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -59,9 +59,12 @@ bool GetMpdOptions(edash_packager::MpdOptions* mpd_options);
|
|||
/// "audio" to select the first audio track, "video" to select the first
|
||||
/// video track, or a decimal number indicating which track number to
|
||||
/// select (start at "1").
|
||||
/// @param language_override is a string which, if non-empty, overrides the
|
||||
/// stream's language metadata.
|
||||
/// @return true if successful, false otherwise.
|
||||
bool AddStreamToMuxer(const std::vector<MediaStream*>& streams,
|
||||
const std::string& stream_selector,
|
||||
const std::string& language_override,
|
||||
Muxer* muxer);
|
||||
|
||||
} // namespace media
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "packager/base/logging.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/base/strings/string_split.h"
|
||||
#include "packager/mpd/base/language_utils.h"
|
||||
|
||||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
@ -23,6 +24,7 @@ enum FieldType {
|
|||
kOutputField,
|
||||
kSegmentTemplateField,
|
||||
kBandwidthField,
|
||||
kLanguageField,
|
||||
};
|
||||
|
||||
struct FieldNameToTypeMapping {
|
||||
|
@ -43,6 +45,8 @@ const FieldNameToTypeMapping kFieldNameTypeMappings[] = {
|
|||
{ "bandwidth", kBandwidthField },
|
||||
{ "bw", kBandwidthField },
|
||||
{ "bitrate", kBandwidthField },
|
||||
{ "language", kLanguageField },
|
||||
{ "lang", kLanguageField },
|
||||
};
|
||||
|
||||
FieldType GetFieldType(const std::string& field_name) {
|
||||
|
@ -96,6 +100,16 @@ bool InsertStreamDescriptor(const std::string& descriptor_string,
|
|||
descriptor.bandwidth = bw;
|
||||
break;
|
||||
}
|
||||
case kLanguageField: {
|
||||
std::string language = LanguageToISO_639_2(iter->second);
|
||||
if (language == "und") {
|
||||
LOG(ERROR) << "Unknown/invalid language specified: " << iter->second;
|
||||
return false;
|
||||
}
|
||||
DCHECK_EQ(3, language.size());
|
||||
descriptor.language = language;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(ERROR) << "Unknown field in stream descriptor (\"" << iter->first
|
||||
<< "\").";
|
||||
|
|
|
@ -26,6 +26,7 @@ struct StreamDescriptor {
|
|||
std::string output;
|
||||
std::string segment_template;
|
||||
uint32_t bandwidth;
|
||||
std::string language;
|
||||
};
|
||||
|
||||
class StreamDescriptorCompareFn {
|
||||
|
|
|
@ -60,6 +60,8 @@ class StreamInfo : public base::RefCountedThreadSafe<StreamInfo> {
|
|||
codec_string_ = codec_string;
|
||||
}
|
||||
|
||||
void set_language(const std::string& language) { language_ = language; }
|
||||
|
||||
protected:
|
||||
friend class base::RefCountedThreadSafe<StreamInfo>;
|
||||
virtual ~StreamInfo();
|
||||
|
|
|
@ -141,10 +141,14 @@ void MP4Muxer::InitializeTrak(const StreamInfo* info, Track* trak) {
|
|||
trak->media.header.timescale = info->time_scale();
|
||||
trak->media.header.duration = 0;
|
||||
if (!info->language().empty()) {
|
||||
DCHECK_EQ(info->language().size(),
|
||||
arraysize(trak->media.header.language) - 1);
|
||||
strcpy(trak->media.header.language, info->language().c_str());
|
||||
trak->media.header.language[info->language().size()] = '\0';
|
||||
const size_t language_size = arraysize(trak->media.header.language) - 1;
|
||||
if (info->language().size() != language_size) {
|
||||
LOG(WARNING) << "'" << info->language() << "' is not a valid ISO-639-2 "
|
||||
<< "language code, ignoring.";
|
||||
} else {
|
||||
memcpy(trak->media.header.language, info->language().c_str(),
|
||||
language_size + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue