1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This standalone binary is a helper for diagnosing seek behavior of the
// demuxer setup in media/ code. It answers the question: "if I ask the demuxer
// to Seek to X ms, where will it actually seek to? (necessitating
// frame-dropping until the original seek target is reached)". Sample run:
//
// $ ./out/Debug/seek_tester .../LayoutTests/media/content/test.ogv 6300
// [0207/130327:INFO:seek_tester.cc(63)] Requested: 6123ms
// [0207/130327:INFO:seek_tester.cc(68)] audio seeked to: 5526ms
// [0207/130327:INFO:seek_tester.cc(74)] video seeked to: 5577ms
#include "base/at_exit.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/string_number_conversions.h"
#include "media/base/media.h"
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/file_data_source.h"
void QuitMessageLoop(MessageLoop* loop, media::PipelineStatus status) {
CHECK_EQ(status, media::PIPELINE_OK);
loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
void TimestampExtractor(uint64* timestamp_ms,
MessageLoop* loop,
const scoped_refptr<media::Buffer>& buffer) {
if (buffer->GetTimestamp() == media::kNoTimestamp())
*timestamp_ms = -1;
else
*timestamp_ms = buffer->GetTimestamp().InMillisecondsF();
loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
int main(int argc, char** argv) {
base::AtExitManager at_exit;
media::InitializeMediaLibraryForTesting();
CHECK_EQ(argc, 3) << "\nUsage: " << argv[0] << " <file> <seekTimeInMs>";
uint64 seek_target_ms;
CHECK(base::StringToUint64(argv[2], &seek_target_ms));
scoped_refptr<media::FileDataSource> file_data_source(
new media::FileDataSource());
CHECK_EQ(file_data_source->Initialize(argv[1]), media::PIPELINE_OK);
MessageLoop loop;
media::PipelineStatusCB quitter = base::Bind(&QuitMessageLoop, &loop);
scoped_refptr<media::FFmpegDemuxer> demuxer(
new media::FFmpegDemuxer(&loop, true));
demuxer->Initialize(file_data_source, quitter);
loop.Run();
demuxer->Seek(base::TimeDelta::FromMilliseconds(seek_target_ms), quitter);
loop.Run();
uint64 audio_seeked_to_ms;
uint64 video_seeked_to_ms;
scoped_refptr<media::DemuxerStream> audio_stream(
demuxer->GetStream(media::DemuxerStream::AUDIO));
scoped_refptr<media::DemuxerStream> video_stream(
demuxer->GetStream(media::DemuxerStream::VIDEO));
LOG(INFO) << "Requested: " << seek_target_ms << "ms";
if (audio_stream) {
audio_stream->Read(base::Bind(
&TimestampExtractor, &audio_seeked_to_ms, &loop));
loop.Run();
LOG(INFO) << " audio seeked to: " << audio_seeked_to_ms << "ms";
}
if (video_stream) {
video_stream->Read(
base::Bind(&TimestampExtractor, &video_seeked_to_ms, &loop));
loop.Run();
LOG(INFO) << " video seeked to: " << video_seeked_to_ms << "ms";
}
demuxer->Stop(base::Bind(&MessageLoop::Quit, base::Unretained(&loop)));
loop.Run();
return 0;
}
|