1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/base/media_log.h"
9 #include "base/atomic_sequence_num.h"
10 #include "base/json/json_writer.h"
11 #include "base/logging.h"
12 #include "base/values.h"
16 // A count of all MediaLogs created in the current process. Used to generate
18 static base::StaticAtomicSequenceNumber g_media_log_count
;
20 std::string
MediaLog::MediaLogLevelToString(MediaLogLevel level
) {
33 MediaLogEvent::Type
MediaLog::MediaLogLevelToEventType(MediaLogLevel level
) {
36 return MediaLogEvent::MEDIA_ERROR_LOG_ENTRY
;
38 return MediaLogEvent::MEDIA_INFO_LOG_ENTRY
;
40 return MediaLogEvent::MEDIA_DEBUG_LOG_ENTRY
;
43 return MediaLogEvent::MEDIA_ERROR_LOG_ENTRY
;
46 std::string
MediaLog::EventTypeToString(MediaLogEvent::Type type
) {
48 case MediaLogEvent::WEBMEDIAPLAYER_CREATED
:
49 return "WEBMEDIAPLAYER_CREATED";
50 case MediaLogEvent::WEBMEDIAPLAYER_DESTROYED
:
51 return "WEBMEDIAPLAYER_DESTROYED";
52 case MediaLogEvent::PIPELINE_CREATED
:
53 return "PIPELINE_CREATED";
54 case MediaLogEvent::PIPELINE_DESTROYED
:
55 return "PIPELINE_DESTROYED";
56 case MediaLogEvent::LOAD
:
58 case MediaLogEvent::SEEK
:
60 case MediaLogEvent::PLAY
:
62 case MediaLogEvent::PAUSE
:
64 case MediaLogEvent::PIPELINE_STATE_CHANGED
:
65 return "PIPELINE_STATE_CHANGED";
66 case MediaLogEvent::PIPELINE_ERROR
:
67 return "PIPELINE_ERROR";
68 case MediaLogEvent::VIDEO_SIZE_SET
:
69 return "VIDEO_SIZE_SET";
70 case MediaLogEvent::DURATION_SET
:
71 return "DURATION_SET";
72 case MediaLogEvent::TOTAL_BYTES_SET
:
73 return "TOTAL_BYTES_SET";
74 case MediaLogEvent::NETWORK_ACTIVITY_SET
:
75 return "NETWORK_ACTIVITY_SET";
76 case MediaLogEvent::ENDED
:
78 case MediaLogEvent::TEXT_ENDED
:
80 case MediaLogEvent::BUFFERED_EXTENTS_CHANGED
:
81 return "BUFFERED_EXTENTS_CHANGED";
82 case MediaLogEvent::MEDIA_ERROR_LOG_ENTRY
:
83 return "MEDIA_ERROR_LOG_ENTRY";
84 case MediaLogEvent::MEDIA_INFO_LOG_ENTRY
:
85 return "MEDIA_INFO_LOG_ENTRY";
86 case MediaLogEvent::MEDIA_DEBUG_LOG_ENTRY
:
87 return "MEDIA_DEBUG_LOG_ENTRY";
88 case MediaLogEvent::PROPERTY_CHANGE
:
89 return "PROPERTY_CHANGE";
95 std::string
MediaLog::PipelineStatusToString(PipelineStatus status
) {
98 return "pipeline: ok";
99 case PIPELINE_ERROR_URL_NOT_FOUND
:
100 return "pipeline: url not found";
101 case PIPELINE_ERROR_NETWORK
:
102 return "pipeline: network error";
103 case PIPELINE_ERROR_DECODE
:
104 return "pipeline: decode error";
105 case PIPELINE_ERROR_DECRYPT
:
106 return "pipeline: decrypt error";
107 case PIPELINE_ERROR_ABORT
:
108 return "pipeline: abort";
109 case PIPELINE_ERROR_INITIALIZATION_FAILED
:
110 return "pipeline: initialization failed";
111 case PIPELINE_ERROR_COULD_NOT_RENDER
:
112 return "pipeline: could not render";
113 case PIPELINE_ERROR_READ
:
114 return "pipeline: read error";
115 case PIPELINE_ERROR_OPERATION_PENDING
:
116 return "pipeline: operation pending";
117 case PIPELINE_ERROR_INVALID_STATE
:
118 return "pipeline: invalid state";
119 case DEMUXER_ERROR_COULD_NOT_OPEN
:
120 return "demuxer: could not open";
121 case DEMUXER_ERROR_COULD_NOT_PARSE
:
122 return "demuxer: could not parse";
123 case DEMUXER_ERROR_NO_SUPPORTED_STREAMS
:
124 return "demuxer: no supported streams";
125 case DECODER_ERROR_NOT_SUPPORTED
:
126 return "decoder: not supported";
132 std::string
MediaLog::MediaEventToLogString(const MediaLogEvent
& event
) {
133 // Special case for PIPELINE_ERROR, since that's by far the most useful
134 // event for figuring out media pipeline failures, and just reporting
135 // pipeline status as numeric code is not very helpful/user-friendly.
137 if (event
.type
== MediaLogEvent::PIPELINE_ERROR
&&
138 event
.params
.GetInteger("pipeline_error", &error_code
)) {
139 PipelineStatus status
= static_cast<PipelineStatus
>(error_code
);
140 return EventTypeToString(event
.type
) + " " +
141 media::MediaLog::PipelineStatusToString(status
);
143 std::string params_json
;
144 base::JSONWriter::Write(&event
.params
, ¶ms_json
);
145 return EventTypeToString(event
.type
) + " " + params_json
;
148 MediaLog::MediaLog() : id_(g_media_log_count
.GetNext()) {}
150 MediaLog::~MediaLog() {}
152 void MediaLog::AddEvent(scoped_ptr
<MediaLogEvent
> event
) {}
154 scoped_ptr
<MediaLogEvent
> MediaLog::CreateEvent(MediaLogEvent::Type type
) {
155 scoped_ptr
<MediaLogEvent
> event(new MediaLogEvent
);
158 event
->time
= base::TimeTicks::Now();
162 scoped_ptr
<MediaLogEvent
> MediaLog::CreateBooleanEvent(
163 MediaLogEvent::Type type
,
164 const std::string
& property
,
166 scoped_ptr
<MediaLogEvent
> event(CreateEvent(type
));
167 event
->params
.SetBoolean(property
, value
);
171 scoped_ptr
<MediaLogEvent
> MediaLog::CreateStringEvent(
172 MediaLogEvent::Type type
,
173 const std::string
& property
,
174 const std::string
& value
) {
175 scoped_ptr
<MediaLogEvent
> event(CreateEvent(type
));
176 event
->params
.SetString(property
, value
);
180 scoped_ptr
<MediaLogEvent
> MediaLog::CreateTimeEvent(
181 MediaLogEvent::Type type
,
182 const std::string
& property
,
183 base::TimeDelta value
) {
184 scoped_ptr
<MediaLogEvent
> event(CreateEvent(type
));
186 event
->params
.SetString(property
, "unknown");
188 event
->params
.SetDouble(property
, value
.InSecondsF());
192 scoped_ptr
<MediaLogEvent
> MediaLog::CreateLoadEvent(const std::string
& url
) {
193 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::LOAD
));
194 event
->params
.SetString("url", url
);
198 scoped_ptr
<MediaLogEvent
> MediaLog::CreateSeekEvent(float seconds
) {
199 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::SEEK
));
200 event
->params
.SetDouble("seek_target", seconds
);
204 scoped_ptr
<MediaLogEvent
> MediaLog::CreatePipelineStateChangedEvent(
205 Pipeline::State state
) {
206 scoped_ptr
<MediaLogEvent
> event(
207 CreateEvent(MediaLogEvent::PIPELINE_STATE_CHANGED
));
208 event
->params
.SetString("pipeline_state", Pipeline::GetStateString(state
));
212 scoped_ptr
<MediaLogEvent
> MediaLog::CreatePipelineErrorEvent(
213 PipelineStatus error
) {
214 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PIPELINE_ERROR
));
215 event
->params
.SetInteger("pipeline_error", error
);
219 scoped_ptr
<MediaLogEvent
> MediaLog::CreateVideoSizeSetEvent(
220 size_t width
, size_t height
) {
221 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::VIDEO_SIZE_SET
));
222 event
->params
.SetInteger("width", width
);
223 event
->params
.SetInteger("height", height
);
227 scoped_ptr
<MediaLogEvent
> MediaLog::CreateBufferedExtentsChangedEvent(
228 int64 start
, int64 current
, int64 end
) {
229 scoped_ptr
<MediaLogEvent
> event(
230 CreateEvent(MediaLogEvent::BUFFERED_EXTENTS_CHANGED
));
231 // These values are headed to JS where there is no int64 so we use a double
232 // and accept loss of precision above 2^53 bytes (8 Exabytes).
233 event
->params
.SetDouble("buffer_start", start
);
234 event
->params
.SetDouble("buffer_current", current
);
235 event
->params
.SetDouble("buffer_end", end
);
239 void MediaLog::AddLogEvent(MediaLogLevel level
, const std::string
& message
) {
240 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogLevelToEventType(level
)));
241 event
->params
.SetString(MediaLogLevelToString(level
), message
);
242 AddEvent(event
.Pass());
245 void MediaLog::SetStringProperty(
246 const std::string
& key
, const std::string
& value
) {
247 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
248 event
->params
.SetString(key
, value
);
249 AddEvent(event
.Pass());
252 void MediaLog::SetIntegerProperty(
253 const std::string
& key
, int value
) {
254 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
255 event
->params
.SetInteger(key
, value
);
256 AddEvent(event
.Pass());
259 void MediaLog::SetDoubleProperty(
260 const std::string
& key
, double value
) {
261 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
262 event
->params
.SetDouble(key
, value
);
263 AddEvent(event
.Pass());
266 void MediaLog::SetBooleanProperty(
267 const std::string
& key
, bool value
) {
268 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
269 event
->params
.SetBoolean(key
, value
);
270 AddEvent(event
.Pass());
273 void MediaLog::SetTimeProperty(
274 const std::string
& key
, base::TimeDelta value
) {
275 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
277 event
->params
.SetString(key
, "unknown");
279 event
->params
.SetDouble(key
, value
.InSecondsF());
280 AddEvent(event
.Pass());
283 LogHelper::LogHelper(MediaLog::MediaLogLevel level
, const LogCB
& log_cb
)
284 : level_(level
), log_cb_(log_cb
) {
287 LogHelper::~LogHelper() {
288 if (log_cb_
.is_null())
290 log_cb_
.Run(level_
, stream_
.str());