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"
7 #include "base/atomic_sequence_num.h"
8 #include "base/json/json_writer.h"
9 #include "base/values.h"
13 // A count of all MediaLogs created in the current process. Used to generate
15 static base::StaticAtomicSequenceNumber g_media_log_count
;
17 std::string
MediaLog::MediaLogLevelToString(MediaLogLevel level
) {
30 MediaLogEvent::Type
MediaLog::MediaLogLevelToEventType(MediaLogLevel level
) {
33 return MediaLogEvent::MEDIA_ERROR_LOG_ENTRY
;
35 return MediaLogEvent::MEDIA_INFO_LOG_ENTRY
;
37 return MediaLogEvent::MEDIA_DEBUG_LOG_ENTRY
;
40 return MediaLogEvent::MEDIA_ERROR_LOG_ENTRY
;
43 std::string
MediaLog::EventTypeToString(MediaLogEvent::Type type
) {
45 case MediaLogEvent::WEBMEDIAPLAYER_CREATED
:
46 return "WEBMEDIAPLAYER_CREATED";
47 case MediaLogEvent::WEBMEDIAPLAYER_DESTROYED
:
48 return "WEBMEDIAPLAYER_DESTROYED";
49 case MediaLogEvent::LOAD
:
51 case MediaLogEvent::SEEK
:
53 case MediaLogEvent::PLAY
:
55 case MediaLogEvent::PAUSE
:
57 case MediaLogEvent::PIPELINE_STATE_CHANGED
:
58 return "PIPELINE_STATE_CHANGED";
59 case MediaLogEvent::PIPELINE_ERROR
:
60 return "PIPELINE_ERROR";
61 case MediaLogEvent::VIDEO_SIZE_SET
:
62 return "VIDEO_SIZE_SET";
63 case MediaLogEvent::DURATION_SET
:
64 return "DURATION_SET";
65 case MediaLogEvent::TOTAL_BYTES_SET
:
66 return "TOTAL_BYTES_SET";
67 case MediaLogEvent::NETWORK_ACTIVITY_SET
:
68 return "NETWORK_ACTIVITY_SET";
69 case MediaLogEvent::ENDED
:
71 case MediaLogEvent::TEXT_ENDED
:
73 case MediaLogEvent::BUFFERED_EXTENTS_CHANGED
:
74 return "BUFFERED_EXTENTS_CHANGED";
75 case MediaLogEvent::MEDIA_ERROR_LOG_ENTRY
:
76 return "MEDIA_ERROR_LOG_ENTRY";
77 case MediaLogEvent::MEDIA_INFO_LOG_ENTRY
:
78 return "MEDIA_INFO_LOG_ENTRY";
79 case MediaLogEvent::MEDIA_DEBUG_LOG_ENTRY
:
80 return "MEDIA_DEBUG_LOG_ENTRY";
81 case MediaLogEvent::PROPERTY_CHANGE
:
82 return "PROPERTY_CHANGE";
88 std::string
MediaLog::PipelineStatusToString(PipelineStatus status
) {
91 return "pipeline: ok";
92 case PIPELINE_ERROR_URL_NOT_FOUND
:
93 return "pipeline: url not found";
94 case PIPELINE_ERROR_NETWORK
:
95 return "pipeline: network error";
96 case PIPELINE_ERROR_DECODE
:
97 return "pipeline: decode error";
98 case PIPELINE_ERROR_ABORT
:
99 return "pipeline: abort";
100 case PIPELINE_ERROR_INITIALIZATION_FAILED
:
101 return "pipeline: initialization failed";
102 case PIPELINE_ERROR_COULD_NOT_RENDER
:
103 return "pipeline: could not render";
104 case PIPELINE_ERROR_READ
:
105 return "pipeline: read error";
106 case PIPELINE_ERROR_OPERATION_PENDING
:
107 return "pipeline: operation pending";
108 case PIPELINE_ERROR_INVALID_STATE
:
109 return "pipeline: invalid state";
110 case DEMUXER_ERROR_COULD_NOT_OPEN
:
111 return "demuxer: could not open";
112 case DEMUXER_ERROR_COULD_NOT_PARSE
:
113 return "demuxer: could not parse";
114 case DEMUXER_ERROR_NO_SUPPORTED_STREAMS
:
115 return "demuxer: no supported streams";
116 case DECODER_ERROR_NOT_SUPPORTED
:
117 return "decoder: not supported";
123 std::string
MediaLog::MediaEventToLogString(const MediaLogEvent
& event
) {
124 // Special case for PIPELINE_ERROR, since that's by far the most useful
125 // event for figuring out media pipeline failures, and just reporting
126 // pipeline status as numeric code is not very helpful/user-friendly.
128 if (event
.type
== MediaLogEvent::PIPELINE_ERROR
&&
129 event
.params
.GetInteger("pipeline_error", &error_code
)) {
130 PipelineStatus status
= static_cast<PipelineStatus
>(error_code
);
131 return EventTypeToString(event
.type
) + " " +
132 media::MediaLog::PipelineStatusToString(status
);
134 std::string params_json
;
135 base::JSONWriter::Write(event
.params
, ¶ms_json
);
136 return EventTypeToString(event
.type
) + " " + params_json
;
139 MediaLog::MediaLog() : id_(g_media_log_count
.GetNext()) {}
141 MediaLog::~MediaLog() {}
143 void MediaLog::AddEvent(scoped_ptr
<MediaLogEvent
> event
) {}
145 scoped_ptr
<MediaLogEvent
> MediaLog::CreateEvent(MediaLogEvent::Type type
) {
146 scoped_ptr
<MediaLogEvent
> event(new MediaLogEvent
);
149 event
->time
= base::TimeTicks::Now();
153 scoped_ptr
<MediaLogEvent
> MediaLog::CreateBooleanEvent(
154 MediaLogEvent::Type type
,
155 const std::string
& property
,
157 scoped_ptr
<MediaLogEvent
> event(CreateEvent(type
));
158 event
->params
.SetBoolean(property
, value
);
162 scoped_ptr
<MediaLogEvent
> MediaLog::CreateStringEvent(
163 MediaLogEvent::Type type
,
164 const std::string
& property
,
165 const std::string
& value
) {
166 scoped_ptr
<MediaLogEvent
> event(CreateEvent(type
));
167 event
->params
.SetString(property
, value
);
171 scoped_ptr
<MediaLogEvent
> MediaLog::CreateTimeEvent(
172 MediaLogEvent::Type type
,
173 const std::string
& property
,
174 base::TimeDelta value
) {
175 scoped_ptr
<MediaLogEvent
> event(CreateEvent(type
));
177 event
->params
.SetString(property
, "unknown");
179 event
->params
.SetDouble(property
, value
.InSecondsF());
183 scoped_ptr
<MediaLogEvent
> MediaLog::CreateLoadEvent(const std::string
& url
) {
184 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::LOAD
));
185 event
->params
.SetString("url", url
);
189 scoped_ptr
<MediaLogEvent
> MediaLog::CreateSeekEvent(float seconds
) {
190 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::SEEK
));
191 event
->params
.SetDouble("seek_target", seconds
);
195 scoped_ptr
<MediaLogEvent
> MediaLog::CreatePipelineStateChangedEvent(
196 Pipeline::State state
) {
197 scoped_ptr
<MediaLogEvent
> event(
198 CreateEvent(MediaLogEvent::PIPELINE_STATE_CHANGED
));
199 event
->params
.SetString("pipeline_state", Pipeline::GetStateString(state
));
203 scoped_ptr
<MediaLogEvent
> MediaLog::CreatePipelineErrorEvent(
204 PipelineStatus error
) {
205 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PIPELINE_ERROR
));
206 event
->params
.SetInteger("pipeline_error", error
);
210 scoped_ptr
<MediaLogEvent
> MediaLog::CreateVideoSizeSetEvent(
211 size_t width
, size_t height
) {
212 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::VIDEO_SIZE_SET
));
213 event
->params
.SetInteger("width", width
);
214 event
->params
.SetInteger("height", height
);
218 scoped_ptr
<MediaLogEvent
> MediaLog::CreateBufferedExtentsChangedEvent(
219 int64 start
, int64 current
, int64 end
) {
220 scoped_ptr
<MediaLogEvent
> event(
221 CreateEvent(MediaLogEvent::BUFFERED_EXTENTS_CHANGED
));
222 // These values are headed to JS where there is no int64 so we use a double
223 // and accept loss of precision above 2^53 bytes (8 Exabytes).
224 event
->params
.SetDouble("buffer_start", start
);
225 event
->params
.SetDouble("buffer_current", current
);
226 event
->params
.SetDouble("buffer_end", end
);
230 void MediaLog::AddLogEvent(MediaLogLevel level
, const std::string
& message
) {
231 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogLevelToEventType(level
)));
232 event
->params
.SetString(MediaLogLevelToString(level
), message
);
233 AddEvent(event
.Pass());
236 void MediaLog::SetStringProperty(
237 const std::string
& key
, const std::string
& value
) {
238 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
239 event
->params
.SetString(key
, value
);
240 AddEvent(event
.Pass());
243 void MediaLog::SetIntegerProperty(
244 const std::string
& key
, int value
) {
245 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
246 event
->params
.SetInteger(key
, value
);
247 AddEvent(event
.Pass());
250 void MediaLog::SetDoubleProperty(
251 const std::string
& key
, double value
) {
252 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
253 event
->params
.SetDouble(key
, value
);
254 AddEvent(event
.Pass());
257 void MediaLog::SetBooleanProperty(
258 const std::string
& key
, bool value
) {
259 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
260 event
->params
.SetBoolean(key
, value
);
261 AddEvent(event
.Pass());
264 void MediaLog::SetTimeProperty(
265 const std::string
& key
, base::TimeDelta value
) {
266 scoped_ptr
<MediaLogEvent
> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE
));
268 event
->params
.SetString(key
, "unknown");
270 event
->params
.SetDouble(key
, value
.InSecondsF());
271 AddEvent(event
.Pass());
274 LogHelper::LogHelper(MediaLog::MediaLogLevel level
,
275 const scoped_refptr
<MediaLog
>& media_log
)
276 : level_(level
), media_log_(media_log
) {
277 DCHECK(media_log_
.get());
280 LogHelper::~LogHelper() {
281 media_log_
->AddLogEvent(level_
, stream_
.str());