Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(790)

Unified Diff: media/webm/webm_stream_parser.cc

Issue 13419002: Media Source dispatches inband text tracks (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: clean compile Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/webm/webm_stream_parser.cc
diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc
index fb070a9210a83f488aff73c41e2bd06736a84f82..3e6ad6bf4857539652190c070d3ca617cf71305b 100644
--- a/media/webm/webm_stream_parser.cc
+++ b/media/webm/webm_stream_parser.cc
@@ -17,6 +17,95 @@
namespace media {
+// To fetch lines of text from embedded WebVTT cues.
+class WebVTTParser {
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 This should be in its own file.
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
+ public:
+ // The payload is the embedded WebVTT cue, stored in a WebM block.
+ // The parser treats this as a UTF-8 byte stream.
+ WebVTTParser(const uint8* payload, int payload_size);
+
+ // Parse the cue identifier, settings, and content from the stream.
+ void operator()(std::string* id, std::string* settings, std::string* content);
+ private:
+ // Remove a byte from the stream, advancing the stream pointer.
+ // Returns true if a character was returned; false means "end of stream".
+ bool GetChar(char* c);
+
+ // Backup the stream pointer.
+ void UngetChar();
+
+ // Parse a line of text from the stream.
+ void ParseLine(std::string* line);
+
+ // Represents the portion of the stream that has not been consumed yet.
+ const uint8* ptr_;
+ const uint8* const ptr_end_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebVTTParser);
+};
+
+WebVTTParser::WebVTTParser(const uint8* payload, int payload_size)
+ : ptr_(payload),
+ ptr_end_(payload + payload_size) {
+}
+
+void WebVTTParser::operator()(std::string* id,
+ std::string* settings,
+ std::string* content) {
+ ParseLine(id);
+ ParseLine(settings);
+ content->assign(ptr_, ptr_end_);
+}
+
+bool WebVTTParser::GetChar(char* c) {
+ if (ptr_ >= ptr_end_)
+ return false; // EOF
+
+ *c = *ptr_++;
+ return true;
+}
+
+void WebVTTParser::UngetChar() {
+ --ptr_;
+}
+
+void WebVTTParser::ParseLine(std::string* line_ptr) {
+ std::string& line = *line_ptr;
+ line.clear();
+
+ // Consume characters from the stream, until we reach end-of-line.
+
+ // The WebVTT spec states that lines may be terminated in any of the following
+ // three ways:
+ // LF
+ // CR
+ // CR LF
+
+ // The spec is here:
+ // http://wiki.webmproject.org/webm-metadata/temporal-metadata/webvtt-in-webm
+
+ enum {
+ kLF = '\x0A',
+ kCR = '\x0D'
+ };
+
+ for (;;) {
+ char c;
+
+ if (!GetChar(&c) || c == kLF)
+ return;
+
+ if (c == kCR) {
+ if (GetChar(&c) && c != kLF)
+ UngetChar();
+
+ return;
+ }
+
+ line.push_back(c);
+ }
+}
+
WebMStreamParser::WebMStreamParser()
: state_(kWaitingForInit),
waiting_for_buffers_(false) {
@@ -29,6 +118,7 @@ void WebMStreamParser::Init(const InitCB& init_cb,
const NewBuffersCB& audio_cb,
const NewBuffersCB& video_cb,
const NeedKeyCB& need_key_cb,
+ const AddTextTrackCB& add_text_track_cb,
const NewMediaSegmentCB& new_segment_cb,
const base::Closure& end_of_segment_cb,
const LogCB& log_cb) {
@@ -47,6 +137,7 @@ void WebMStreamParser::Init(const InitCB& init_cb,
audio_cb_ = audio_cb;
video_cb_ = video_cb;
need_key_cb_ = need_key_cb;
+ add_text_track_cb_ = add_text_track_cb;
new_segment_cb_ = new_segment_cb;
end_of_segment_cb_ = end_of_segment_cb;
log_cb_ = log_cb;
@@ -198,6 +289,20 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
return -1;
}
+ typedef std::set<int> TextTracksSet;
+ const TextTracksSet& text_tracks = tracks_parser.text_tracks();
+
+ for (TextTracksSet::const_iterator itr = text_tracks.begin();
+ itr != text_tracks.end(); ++itr) {
+ // TODO(matthewjheaney): parse track kind, name, lang
+ // Must also resolve ptr type
+ TextTrack* const text_cb = add_text_track_cb_.Run(kTextSubtitles, "", "");
+
+ // TODO(matthewjheaney): we need to explicitly deallocate text_cb,
+ // unless a scoped_ptr or somesuch is used.
+ text_track_map_.insert(std::make_pair(*itr, text_cb));
+ }
+
cluster_parser_.reset(new WebMClusterParser(
info_parser.timecode_scale(),
tracks_parser.audio_track_num(),
@@ -268,6 +373,22 @@ int WebMStreamParser::ParseCluster(const uint8* data, int size) {
if (!video_buffers.empty() && !video_cb_.Run(video_buffers))
return -1;
+ WebMClusterParser::TextTrackIterator tt_iter =
+ cluster_parser_->CreateTextTrackIterator();
+
+ int tt_num;
+ const BufferQueue* tt_buffers;
+
+ while (tt_iter(&tt_num, &tt_buffers)) {
+ TextTrackMap::iterator cb_iter = text_track_map_.find(tt_num);
+
+ if (cb_iter == text_track_map_.end())
+ continue;
+
+ TextTrack* const text_cb = cb_iter->second;
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 nit: Just inline this in the call below.
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
+ OnTextBuffers(*tt_buffers, text_cb);
+ }
+
if (cluster_ended)
end_of_segment_cb_.Run();
@@ -282,4 +403,31 @@ void WebMStreamParser::FireNeedKey(const std::string& key_id) {
need_key_cb_.Run(kWebMEncryptInitDataType, key_id_array.Pass(), key_id_size);
}
+void WebMStreamParser::OnTextBuffers(const StreamParser::BufferQueue& buffers,
+ TextTrack* text_cb) {
+ // TODO(matthewjheaney): where is this done?
+ //AdjustBufferTimestamps(buffers);
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 This happens in SourceState::OnBuffers so you this
Matthew Heaney (Chromium) 2013/05/10 05:21:08 Done.
+
+ for (StreamParser::BufferQueue::const_iterator itr = buffers.begin();
+ itr != buffers.end(); ++itr) {
+ OnTextBuffer(*itr, text_cb);
+ }
+}
+
+void WebMStreamParser::OnTextBuffer(const StreamParserBuffer* buffer,
+ TextTrack* text_cb) {
+ const base::TimeDelta start = buffer->GetTimestamp();
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 nit: Since most of these locals appear to only be
Matthew Heaney (Chromium) 2013/05/10 05:21:08 This function was cleaned up a bit because the par
+ const base::TimeDelta end = start + buffer->GetDuration();
+
+ const uint8* const payload = buffer->GetData();
+ const int payload_size = buffer->GetDataSize();
+
+ WebVTTParser parser(payload, payload_size);
+ std::string id, settings, content;
+
+ parser(&id, &settings, &content);
acolwell GONE FROM CHROMIUM 2013/05/10 02:22:08 Seeing as it looks like you could rearrange this c
Matthew Heaney (Chromium) 2013/05/10 05:21:08 I moved the webvtt parser to its own class, and ad
+
+ text_cb->addWebVTTCue(start, end, id, content, settings);
+}
+
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698