Index: media/filters/ffmpeg_demuxer.cc |
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc |
index de1968afc43d200f86f0eeb3791621ce72d54d72..cbee00c65a0ebd4cf05170eae2bc3ade990eab35 100644 |
--- a/media/filters/ffmpeg_demuxer.cc |
+++ b/media/filters/ffmpeg_demuxer.cc |
@@ -14,6 +14,7 @@ |
#include "base/memory/scoped_ptr.h" |
#include "base/message_loop/message_loop_proxy.h" |
#include "base/metrics/sparse_histogram.h" |
+#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_util.h" |
#include "base/strings/stringprintf.h" |
#include "base/sys_byteorder.h" |
@@ -34,6 +35,38 @@ |
namespace media { |
+static base::Time ExtractTimelineOffset(AVFormatContext* format_context) { |
scherkus (not reviewing)
2014/04/15 00:53:40
parsing code without tests makes me nervous
how a
acolwell GONE FROM CHROMIUM
2014/04/16 01:01:08
Done.
|
+ if (strstr(format_context->iformat->name, "webm") || |
+ strstr(format_context->iformat->name, "matroska")) { |
+ const AVDictionaryEntry* entry = |
+ av_dict_get(format_context->metadata, "creation_time", NULL, 0); |
+ |
+ // Convert ffmpeg UTC representation (YYYY-MM-DD HH:MM:SS) to base::Time. |
scherkus (not reviewing)
2014/04/15 00:53:40
s/ffmpeg/FFmpeg/
acolwell GONE FROM CHROMIUM
2014/04/16 01:01:08
Done.
|
+ std::vector<std::string> fields; |
+ std::vector<std::string> date_fields; |
+ std::vector<std::string> time_fields; |
+ base::Time::Exploded exploded; |
+ exploded.millisecond = 0; |
+ |
+ // TODO: Update this parsing code when FFmpeg returns sub-second |
scherkus (not reviewing)
2014/04/15 00:53:40
TODO(acolwell)?
acolwell GONE FROM CHROMIUM
2014/04/16 01:01:08
Done.
|
+ // information. |
+ if (entry != NULL && entry->value != NULL && |
+ (Tokenize(entry->value, " ", &fields) == 2) && |
+ (Tokenize(fields[0], "-", &date_fields) == 3) && |
+ (Tokenize(fields[1], ":", &time_fields) == 3) && |
+ base::StringToInt(date_fields[0], &exploded.year) && |
+ base::StringToInt(date_fields[1], &exploded.month) && |
+ base::StringToInt(date_fields[2], &exploded.day_of_month) && |
+ base::StringToInt(time_fields[0], &exploded.hour) && |
+ base::StringToInt(time_fields[1], &exploded.minute) && |
+ base::StringToInt(time_fields[2], &exploded.second)) { |
+ return base::Time::FromUTCExploded(exploded); |
+ } |
+ } |
+ |
+ return base::Time(); |
+} |
+ |
// |
// FFmpegDemuxerStream |
// |
@@ -486,6 +519,10 @@ base::TimeDelta FFmpegDemuxer::GetStartTime() const { |
return start_time_; |
} |
+base::Time FFmpegDemuxer::GetWallclockTimelineOffset() const { |
+ return wallclock_timeline_offset_; |
+} |
+ |
void FFmpegDemuxer::AddTextStreams() { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
@@ -674,6 +711,8 @@ void FFmpegDemuxer::OnFindStreamInfoDone(const PipelineStatusCB& status_cb, |
if (strcmp(format_context->iformat->name, "avi") == 0) |
format_context->flags |= AVFMT_FLAG_GENPTS; |
+ wallclock_timeline_offset_ = ExtractTimelineOffset(format_context); |
+ |
// Good to go: set the duration and bitrate and notify we're done |
// initializing. |
host_->SetDuration(max_duration); |