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.
4
5#include "media/base/media_log.h"
6
7#include <string>
8
9#include "base/atomic_sequence_num.h"
10#include "base/logging.h"
11#include "base/values.h"
12
13namespace media {
14
15// A count of all MediaLogs created in the current process. Used to generate
16// unique IDs.
17static base::StaticAtomicSequenceNumber g_media_log_count;
18
19const char* MediaLog::EventTypeToString(MediaLogEvent::Type type) {
20  switch (type) {
21    case MediaLogEvent::WEBMEDIAPLAYER_CREATED:
22      return "WEBMEDIAPLAYER_CREATED";
23    case MediaLogEvent::WEBMEDIAPLAYER_DESTROYED:
24      return "WEBMEDIAPLAYER_DESTROYED";
25    case MediaLogEvent::PIPELINE_CREATED:
26      return "PIPELINE_CREATED";
27    case MediaLogEvent::PIPELINE_DESTROYED:
28      return "PIPELINE_DESTROYED";
29    case MediaLogEvent::LOAD:
30      return "LOAD";
31    case MediaLogEvent::SEEK:
32      return "SEEK";
33    case MediaLogEvent::PLAY:
34      return "PLAY";
35    case MediaLogEvent::PAUSE:
36      return "PAUSE";
37    case MediaLogEvent::PIPELINE_STATE_CHANGED:
38      return "PIPELINE_STATE_CHANGED";
39    case MediaLogEvent::PIPELINE_ERROR:
40      return "PIPELINE_ERROR";
41    case MediaLogEvent::VIDEO_SIZE_SET:
42      return "VIDEO_SIZE_SET";
43    case MediaLogEvent::DURATION_SET:
44      return "DURATION_SET";
45    case MediaLogEvent::TOTAL_BYTES_SET:
46      return "TOTAL_BYTES_SET";
47    case MediaLogEvent::NETWORK_ACTIVITY_SET:
48      return "NETWORK_ACTIVITY_SET";
49    case MediaLogEvent::ENDED:
50      return "ENDED";
51    case MediaLogEvent::TEXT_ENDED:
52      return "TEXT_ENDED";
53    case MediaLogEvent::BUFFERED_EXTENTS_CHANGED:
54      return "BUFFERED_EXTENTS_CHANGED";
55    case MediaLogEvent::MEDIA_SOURCE_ERROR:
56      return "MEDIA_SOURCE_ERROR";
57    case MediaLogEvent::PROPERTY_CHANGE:
58      return "PROPERTY_CHANGE";
59  }
60  NOTREACHED();
61  return NULL;
62}
63
64const char* MediaLog::PipelineStatusToString(PipelineStatus status) {
65  switch (status) {
66    case PIPELINE_OK:
67      return "pipeline: ok";
68    case PIPELINE_ERROR_URL_NOT_FOUND:
69      return "pipeline: url not found";
70    case PIPELINE_ERROR_NETWORK:
71      return "pipeline: network error";
72    case PIPELINE_ERROR_DECODE:
73      return "pipeline: decode error";
74    case PIPELINE_ERROR_DECRYPT:
75      return "pipeline: decrypt error";
76    case PIPELINE_ERROR_ABORT:
77      return "pipeline: abort";
78    case PIPELINE_ERROR_INITIALIZATION_FAILED:
79      return "pipeline: initialization failed";
80    case PIPELINE_ERROR_COULD_NOT_RENDER:
81      return "pipeline: could not render";
82    case PIPELINE_ERROR_READ:
83      return "pipeline: read error";
84    case PIPELINE_ERROR_OPERATION_PENDING:
85      return "pipeline: operation pending";
86    case PIPELINE_ERROR_INVALID_STATE:
87      return "pipeline: invalid state";
88    case DEMUXER_ERROR_COULD_NOT_OPEN:
89      return "demuxer: could not open";
90    case DEMUXER_ERROR_COULD_NOT_PARSE:
91      return "dumuxer: could not parse";
92    case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
93      return "demuxer: no supported streams";
94    case DECODER_ERROR_NOT_SUPPORTED:
95      return "decoder: not supported";
96  }
97  NOTREACHED();
98  return NULL;
99}
100
101LogHelper::LogHelper(const LogCB& log_cb) : log_cb_(log_cb) {}
102
103LogHelper::~LogHelper() {
104  if (log_cb_.is_null())
105    return;
106  log_cb_.Run(stream_.str());
107}
108
109MediaLog::MediaLog() : id_(g_media_log_count.GetNext()) {}
110
111MediaLog::~MediaLog() {}
112
113void MediaLog::AddEvent(scoped_ptr<MediaLogEvent> event) {}
114
115scoped_ptr<MediaLogEvent> MediaLog::CreateEvent(MediaLogEvent::Type type) {
116  scoped_ptr<MediaLogEvent> event(new MediaLogEvent);
117  event->id = id_;
118  event->type = type;
119  event->time = base::TimeTicks::Now();
120  return event.Pass();
121}
122
123scoped_ptr<MediaLogEvent> MediaLog::CreateBooleanEvent(
124    MediaLogEvent::Type type, const char* property, bool value) {
125  scoped_ptr<MediaLogEvent> event(CreateEvent(type));
126  event->params.SetBoolean(property, value);
127  return event.Pass();
128}
129
130scoped_ptr<MediaLogEvent> MediaLog::CreateStringEvent(
131    MediaLogEvent::Type type, const char* property, const std::string& value) {
132  scoped_ptr<MediaLogEvent> event(CreateEvent(type));
133  event->params.SetString(property, value);
134  return event.Pass();
135}
136
137scoped_ptr<MediaLogEvent> MediaLog::CreateTimeEvent(
138    MediaLogEvent::Type type, const char* property, base::TimeDelta value) {
139  scoped_ptr<MediaLogEvent> event(CreateEvent(type));
140  if (value.is_max())
141    event->params.SetString(property, "unknown");
142  else
143    event->params.SetDouble(property, value.InSecondsF());
144  return event.Pass();
145}
146
147scoped_ptr<MediaLogEvent> MediaLog::CreateLoadEvent(const std::string& url) {
148  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::LOAD));
149  event->params.SetString("url", url);
150  return event.Pass();
151}
152
153scoped_ptr<MediaLogEvent> MediaLog::CreateSeekEvent(float seconds) {
154  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::SEEK));
155  event->params.SetDouble("seek_target", seconds);
156  return event.Pass();
157}
158
159scoped_ptr<MediaLogEvent> MediaLog::CreatePipelineStateChangedEvent(
160    Pipeline::State state) {
161  scoped_ptr<MediaLogEvent> event(
162      CreateEvent(MediaLogEvent::PIPELINE_STATE_CHANGED));
163  event->params.SetString("pipeline_state", Pipeline::GetStateString(state));
164  return event.Pass();
165}
166
167scoped_ptr<MediaLogEvent> MediaLog::CreatePipelineErrorEvent(
168    PipelineStatus error) {
169  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PIPELINE_ERROR));
170  event->params.SetString("pipeline_error", PipelineStatusToString(error));
171  return event.Pass();
172}
173
174scoped_ptr<MediaLogEvent> MediaLog::CreateVideoSizeSetEvent(
175    size_t width, size_t height) {
176  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::VIDEO_SIZE_SET));
177  event->params.SetInteger("width", width);
178  event->params.SetInteger("height", height);
179  return event.Pass();
180}
181
182scoped_ptr<MediaLogEvent> MediaLog::CreateBufferedExtentsChangedEvent(
183    int64 start, int64 current, int64 end) {
184  scoped_ptr<MediaLogEvent> event(
185      CreateEvent(MediaLogEvent::BUFFERED_EXTENTS_CHANGED));
186  // These values are headed to JS where there is no int64 so we use a double
187  // and accept loss of precision above 2^53 bytes (8 Exabytes).
188  event->params.SetDouble("buffer_start", start);
189  event->params.SetDouble("buffer_current", current);
190  event->params.SetDouble("buffer_end", end);
191  return event.Pass();
192}
193
194scoped_ptr<MediaLogEvent> MediaLog::CreateMediaSourceErrorEvent(
195    const std::string& error) {
196  scoped_ptr<MediaLogEvent> event(
197      CreateEvent(MediaLogEvent::MEDIA_SOURCE_ERROR));
198  event->params.SetString("error", error);
199  return event.Pass();
200}
201
202void MediaLog::SetStringProperty(
203    const char* key, const std::string& value) {
204  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
205  event->params.SetString(key, value);
206  AddEvent(event.Pass());
207}
208
209void MediaLog::SetIntegerProperty(
210    const char* key, int value) {
211  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
212  event->params.SetInteger(key, value);
213  AddEvent(event.Pass());
214}
215
216void MediaLog::SetDoubleProperty(
217    const char* key, double value) {
218  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
219  event->params.SetDouble(key, value);
220  AddEvent(event.Pass());
221}
222
223void MediaLog::SetBooleanProperty(
224    const char* key, bool value) {
225  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
226  event->params.SetBoolean(key, value);
227  AddEvent(event.Pass());
228}
229
230void MediaLog::SetTimeProperty(
231    const char* key, base::TimeDelta value) {
232  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
233  if (value.is_max())
234    event->params.SetString(key, "unknown");
235  else
236    event->params.SetDouble(key, value.InSecondsF());
237  AddEvent(event.Pass());
238}
239
240}  //namespace media
241