Chromium Code Reviews| 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 |