Full vtt in mp4 path
Change-Id: I7f49dbfed188ff7a451b0b4fbd6947590e8935d1
This commit is contained in:
parent
ec904f3f79
commit
92280bf214
|
@ -82,7 +82,7 @@ const char kUsage[] =
|
|||
" - input (in): Required input/source media file path or network stream\n"
|
||||
" URL.\n"
|
||||
" - stream_selector (stream): Required field with value 'audio',\n"
|
||||
" 'video', or stream number (zero based).\n"
|
||||
" 'video', 'text', or stream number (zero based).\n"
|
||||
" - output (out): Required output file (single file) or initialization\n"
|
||||
" file path (multiple file).\n"
|
||||
" - segment_template (segment): Optional value which specifies the\n"
|
||||
|
@ -253,8 +253,8 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
|
|||
}
|
||||
stream_muxer_options.bandwidth = stream_iter->bandwidth;
|
||||
|
||||
// Handle text input.
|
||||
if (stream_iter->stream_selector == "text") {
|
||||
if (stream_iter->stream_selector == "text" &&
|
||||
stream_iter->output_format != CONTAINER_MOV) {
|
||||
MediaInfo text_media_info;
|
||||
if (!StreamInfoToTextMediaInfo(*stream_iter, stream_muxer_options,
|
||||
&text_media_info)) {
|
||||
|
|
|
@ -33,6 +33,7 @@ const size_t kQueuedSamplesLimit = 10000;
|
|||
const size_t kInvalidStreamIndex = static_cast<size_t>(-1);
|
||||
const size_t kBaseVideoOutputStreamIndex = 0x100;
|
||||
const size_t kBaseAudioOutputStreamIndex = 0x200;
|
||||
const size_t kBaseTextOutputStreamIndex = 0x300;
|
||||
|
||||
std::string GetStreamLabel(size_t stream_index) {
|
||||
switch (stream_index) {
|
||||
|
@ -40,6 +41,8 @@ std::string GetStreamLabel(size_t stream_index) {
|
|||
return "video";
|
||||
case kBaseAudioOutputStreamIndex:
|
||||
return "audio";
|
||||
case kBaseTextOutputStreamIndex:
|
||||
return "text";
|
||||
default:
|
||||
return base::SizeTToString(stream_index);
|
||||
}
|
||||
|
@ -51,11 +54,13 @@ bool GetStreamIndex(const std::string& stream_label, size_t* stream_index) {
|
|||
*stream_index = kBaseVideoOutputStreamIndex;
|
||||
} else if (stream_label == "audio") {
|
||||
*stream_index = kBaseAudioOutputStreamIndex;
|
||||
} else if (stream_label == "text") {
|
||||
*stream_index = kBaseTextOutputStreamIndex;
|
||||
} else {
|
||||
// Expect stream_label to be a zero based stream id.
|
||||
if (!base::StringToSizeT(stream_label, stream_index)) {
|
||||
LOG(ERROR) << "Invalid argument --stream=" << stream_label << "; "
|
||||
<< "should be 'audio', 'video', or a number";
|
||||
<< "should be 'audio', 'video', 'text', or a number";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +226,9 @@ void Demuxer::ParserInitEvent(
|
|||
bool audio_handler_set =
|
||||
output_handlers().find(kBaseAudioOutputStreamIndex) !=
|
||||
output_handlers().end();
|
||||
bool text_handler_set =
|
||||
output_handlers().find(kBaseTextOutputStreamIndex) !=
|
||||
output_handlers().end();
|
||||
for (const std::shared_ptr<StreamInfo>& stream_info : stream_infos) {
|
||||
size_t stream_index = base_stream_index;
|
||||
if (video_handler_set && stream_info->stream_type() == kStreamVideo) {
|
||||
|
@ -233,6 +241,10 @@ void Demuxer::ParserInitEvent(
|
|||
// Only for the first audio stream.
|
||||
audio_handler_set = false;
|
||||
}
|
||||
if (text_handler_set && stream_info->stream_type() == kStreamText) {
|
||||
stream_index = kBaseTextOutputStreamIndex;
|
||||
text_handler_set = false;
|
||||
}
|
||||
|
||||
const bool handler_set =
|
||||
output_handlers().find(stream_index) != output_handlers().end();
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "packager/media/base/audio_stream_info.h"
|
||||
#include "packager/media/base/muxer_options.h"
|
||||
#include "packager/media/base/protection_system_specific_info.h"
|
||||
#include "packager/media/base/text_stream_info.h"
|
||||
#include "packager/media/base/video_stream_info.h"
|
||||
#include "packager/media/codecs/ec3_audio_util.h"
|
||||
#include "packager/mpd/base/media_info.pb.h"
|
||||
|
@ -134,11 +135,29 @@ void AddAudioInfo(const AudioStreamInfo* audio_stream_info,
|
|||
}
|
||||
}
|
||||
|
||||
void AddTextInfo(const TextStreamInfo& text_stream_info,
|
||||
MediaInfo* media_info) {
|
||||
MediaInfo::TextInfo* text_info = media_info->mutable_text_info();
|
||||
// For now, set everything as subtitle.
|
||||
text_info->set_type(MediaInfo::TextInfo::SUBTITLE);
|
||||
if (text_stream_info.codec_string() == "wvtt") {
|
||||
text_info->set_format("vtt");
|
||||
} else {
|
||||
LOG(WARNING) << "Unhandled codec " << text_stream_info.codec_string()
|
||||
<< " copying it as format.";
|
||||
text_info->set_format(text_stream_info.codec_string());
|
||||
}
|
||||
|
||||
text_info->set_language(text_stream_info.language());
|
||||
}
|
||||
|
||||
void SetMediaInfoStreamInfo(const StreamInfo& stream_info,
|
||||
MediaInfo* media_info) {
|
||||
if (stream_info.stream_type() == kStreamAudio) {
|
||||
AddAudioInfo(static_cast<const AudioStreamInfo*>(&stream_info),
|
||||
media_info);
|
||||
} else if (stream_info.stream_type() == kStreamText) {
|
||||
AddTextInfo(static_cast<const TextStreamInfo&>(stream_info), media_info);
|
||||
} else {
|
||||
DCHECK_EQ(stream_info.stream_type(), kStreamVideo);
|
||||
AddVideoInfo(static_cast<const VideoStreamInfo*>(&stream_info),
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "packager/media/base/fourccs.h"
|
||||
#include "packager/media/base/key_source.h"
|
||||
#include "packager/media/base/media_sample.h"
|
||||
#include "packager/media/base/text_stream_info.h"
|
||||
#include "packager/media/base/video_stream_info.h"
|
||||
#include "packager/media/codecs/es_descriptor.h"
|
||||
#include "packager/media/event/muxer_listener.h"
|
||||
|
@ -150,6 +151,10 @@ Status MP4Muxer::InitializeMuxer() {
|
|||
GenerateAudioTrak(static_cast<AudioStreamInfo*>(streams()[i].get()),
|
||||
&trak, i + 1);
|
||||
break;
|
||||
case kStreamText:
|
||||
GenerateTextTrak(static_cast<TextStreamInfo*>(streams()[i].get()),
|
||||
&trak, i + 1);
|
||||
break;
|
||||
default:
|
||||
NOTIMPLEMENTED() << "Not implemented for stream type: "
|
||||
<< streams()[i]->stream_type();
|
||||
|
@ -373,6 +378,31 @@ void MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info,
|
|||
}
|
||||
}
|
||||
|
||||
void MP4Muxer::GenerateTextTrak(const TextStreamInfo* text_info,
|
||||
Track* trak,
|
||||
uint32_t track_id) {
|
||||
InitializeTrak(text_info, trak);
|
||||
|
||||
if (text_info->codec_string() == "wvtt") {
|
||||
// Handle WebVTT.
|
||||
TextSampleEntry webvtt;
|
||||
webvtt.format = FOURCC_wvtt;
|
||||
webvtt.config.config.assign(text_info->codec_config().begin(),
|
||||
text_info->codec_config().end());
|
||||
// TODO(rkuroiwa): This should be the source file URI(s). Putting bogus
|
||||
// string for now so that the box will be there for samples with overlapping
|
||||
// cues.
|
||||
webvtt.label.source_label = "source_label";
|
||||
SampleDescription& sample_description =
|
||||
trak->media.information.sample_table.description;
|
||||
sample_description.type = kText;
|
||||
sample_description.text_entries.push_back(webvtt);
|
||||
return;
|
||||
}
|
||||
NOTIMPLEMENTED() << text_info->codec_string()
|
||||
<< " handling not implemented yet.";
|
||||
}
|
||||
|
||||
bool MP4Muxer::GetInitRangeStartAndEnd(uint32_t* start, uint32_t* end) {
|
||||
DCHECK(start && end);
|
||||
size_t range_offset = 0;
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace media {
|
|||
|
||||
class AudioStreamInfo;
|
||||
class StreamInfo;
|
||||
class TextStreamInfo;
|
||||
class VideoStreamInfo;
|
||||
|
||||
namespace mp4 {
|
||||
|
@ -50,6 +51,9 @@ class MP4Muxer : public Muxer {
|
|||
void GenerateVideoTrak(const VideoStreamInfo* video_info,
|
||||
Track* trak,
|
||||
uint32_t track_id);
|
||||
void GenerateTextTrak(const TextStreamInfo* video_info,
|
||||
Track* trak,
|
||||
uint32_t track_id);
|
||||
|
||||
// Gets |start| and |end| initialization range. Returns true if there is an
|
||||
// init range and sets start-end byte-range-spec specified in RFC2616.
|
||||
|
|
|
@ -707,8 +707,10 @@ Representation* AdaptationSet::AddRepresentation(const MediaInfo& media_info) {
|
|||
std::unique_ptr<Representation> representation(new Representation(
|
||||
media_info, mpd_options_, representation_id, std::move(listener)));
|
||||
|
||||
if (!representation->Init())
|
||||
if (!representation->Init()) {
|
||||
LOG(ERROR) << "Failed to initialize Representation.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// For videos, record the width, height, and the frame rate to calculate the
|
||||
// max {width,height,framerate} required for DASH IOP.
|
||||
|
@ -1383,6 +1385,8 @@ std::string Representation::GetTextMimeType() const {
|
|||
if (media_info_.text_info().format() == "vtt") {
|
||||
if (media_info_.container_type() == MediaInfo::CONTAINER_TEXT) {
|
||||
return "text/vtt";
|
||||
} else if (media_info_.container_type() == MediaInfo::CONTAINER_MP4) {
|
||||
return "application/mp4";
|
||||
}
|
||||
LOG(ERROR) << "Failed to determine MIME type for VTT container: "
|
||||
<< media_info_.container_type();
|
||||
|
|
|
@ -23,6 +23,10 @@ std::string TextCodecString(const MediaInfo& media_info) {
|
|||
(media_info.container_type() == MediaInfo::CONTAINER_MP4)) {
|
||||
return "stpp";
|
||||
}
|
||||
if (format == "vtt" &&
|
||||
(media_info.container_type() == MediaInfo::CONTAINER_MP4)) {
|
||||
return "wvtt";
|
||||
}
|
||||
|
||||
// Otherwise codec doesn't need to be specified, e.g. vtt and ttml+xml are
|
||||
// obvious from the mime type.
|
||||
|
|
Loading…
Reference in New Issue