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::AUDIO_ENDED:
50      return "AUDIO_ENDED";
51    case MediaLogEvent::VIDEO_ENDED:
52      return "VIDEO_ENDED";
53    case MediaLogEvent::AUDIO_RENDERER_DISABLED:
54      return "AUDIO_RENDERER_DISABLED";
55    case MediaLogEvent::BUFFERED_EXTENTS_CHANGED:
56      return "BUFFERED_EXTENTS_CHANGED";
57    case MediaLogEvent::MEDIA_SOURCE_ERROR:
58      return "MEDIA_SOURCE_ERROR";
59    case MediaLogEvent::PROPERTY_CHANGE:
60      return "PROPERTY_CHANGE";
61  }
62  NOTREACHED();
63  return NULL;
64}
65
66const char* MediaLog::PipelineStatusToString(PipelineStatus status) {
67  switch (status) {
68    case PIPELINE_OK:
69      return "pipeline: ok";
70    case PIPELINE_ERROR_URL_NOT_FOUND:
71      return "pipeline: url not found";
72    case PIPELINE_ERROR_NETWORK:
73      return "pipeline: network error";
74    case PIPELINE_ERROR_DECODE:
75      return "pipeline: decode error";
76    case PIPELINE_ERROR_DECRYPT:
77      return "pipeline: decrypt error";
78    case PIPELINE_ERROR_ABORT:
79      return "pipeline: abort";
80    case PIPELINE_ERROR_INITIALIZATION_FAILED:
81      return "pipeline: initialization failed";
82    case PIPELINE_ERROR_COULD_NOT_RENDER:
83      return "pipeline: could not render";
84    case PIPELINE_ERROR_READ:
85      return "pipeline: read error";
86    case PIPELINE_ERROR_OPERATION_PENDING:
87      return "pipeline: operation pending";
88    case PIPELINE_ERROR_INVALID_STATE:
89      return "pipeline: invalid state";
90    case DEMUXER_ERROR_COULD_NOT_OPEN:
91      return "demuxer: could not open";
92    case DEMUXER_ERROR_COULD_NOT_PARSE:
93      return "dumuxer: could not parse";
94    case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
95      return "demuxer: no supported streams";
96    case DECODER_ERROR_NOT_SUPPORTED:
97      return "decoder: not supported";
98    case PIPELINE_STATUS_MAX:
99      NOTREACHED();
100  }
101  NOTREACHED();
102  return NULL;
103}
104
105LogHelper::LogHelper(const LogCB& log_cb) : log_cb_(log_cb) {}
106
107LogHelper::~LogHelper() {
108  if (log_cb_.is_null())
109    return;
110  log_cb_.Run(stream_.str());
111}
112
113MediaLog::MediaLog() : id_(g_media_log_count.GetNext()) {}
114
115MediaLog::~MediaLog() {}
116
117void MediaLog::AddEvent(scoped_ptr<MediaLogEvent> event) {}
118
119scoped_ptr<MediaLogEvent> MediaLog::CreateEvent(MediaLogEvent::Type type) {
120  scoped_ptr<MediaLogEvent> event(new MediaLogEvent);
121  event->id = id_;
122  event->type = type;
123  event->time = base::TimeTicks::Now();
124  return event.Pass();
125}
126
127scoped_ptr<MediaLogEvent> MediaLog::CreateBooleanEvent(
128    MediaLogEvent::Type type, const char* property, bool value) {
129  scoped_ptr<MediaLogEvent> event(CreateEvent(type));
130  event->params.SetBoolean(property, value);
131  return event.Pass();
132}
133
134scoped_ptr<MediaLogEvent> MediaLog::CreateStringEvent(
135    MediaLogEvent::Type type, const char* property, const std::string& value) {
136  scoped_ptr<MediaLogEvent> event(CreateEvent(type));
137  event->params.SetString(property, value);
138  return event.Pass();
139}
140
141scoped_ptr<MediaLogEvent> MediaLog::CreateTimeEvent(
142    MediaLogEvent::Type type, const char* property, base::TimeDelta value) {
143  scoped_ptr<MediaLogEvent> event(CreateEvent(type));
144  event->params.SetDouble(property, value.InSecondsF());
145  return event.Pass();
146}
147
148scoped_ptr<MediaLogEvent> MediaLog::CreateLoadEvent(const std::string& url) {
149  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::LOAD));
150  event->params.SetString("url", url);
151  return event.Pass();
152}
153
154scoped_ptr<MediaLogEvent> MediaLog::CreateSeekEvent(float seconds) {
155  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::SEEK));
156  event->params.SetDouble("seek_target", seconds);
157  return event.Pass();
158}
159
160scoped_ptr<MediaLogEvent> MediaLog::CreatePipelineStateChangedEvent(
161    Pipeline::State state) {
162  scoped_ptr<MediaLogEvent> event(
163      CreateEvent(MediaLogEvent::PIPELINE_STATE_CHANGED));
164  event->params.SetString("pipeline_state", Pipeline::GetStateString(state));
165  return event.Pass();
166}
167
168scoped_ptr<MediaLogEvent> MediaLog::CreatePipelineErrorEvent(
169    PipelineStatus error) {
170  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PIPELINE_ERROR));
171  event->params.SetString("pipeline_error", PipelineStatusToString(error));
172  return event.Pass();
173}
174
175scoped_ptr<MediaLogEvent> MediaLog::CreateVideoSizeSetEvent(
176    size_t width, size_t height) {
177  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::VIDEO_SIZE_SET));
178  event->params.SetInteger("width", width);
179  event->params.SetInteger("height", height);
180  return event.Pass();
181}
182
183scoped_ptr<MediaLogEvent> MediaLog::CreateBufferedExtentsChangedEvent(
184    int64 start, int64 current, int64 end) {
185  scoped_ptr<MediaLogEvent> event(
186      CreateEvent(MediaLogEvent::BUFFERED_EXTENTS_CHANGED));
187  // These values are headed to JS where there is no int64 so we use a double
188  // and accept loss of precision above 2^53 bytes (8 Exabytes).
189  event->params.SetDouble("buffer_start", start);
190  event->params.SetDouble("buffer_current", current);
191  event->params.SetDouble("buffer_end", end);
192  return event.Pass();
193}
194
195scoped_ptr<MediaLogEvent> MediaLog::CreateMediaSourceErrorEvent(
196    const std::string& error) {
197  scoped_ptr<MediaLogEvent> event(
198      CreateEvent(MediaLogEvent::MEDIA_SOURCE_ERROR));
199  event->params.SetString("error", error);
200  return event.Pass();
201}
202
203void MediaLog::SetStringProperty(
204    const char* key, const std::string& value) {
205  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
206  event->params.SetString(key, value);
207  AddEvent(event.Pass());
208}
209
210void MediaLog::SetIntegerProperty(
211    const char* key, int value) {
212  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
213  event->params.SetInteger(key, value);
214  AddEvent(event.Pass());
215}
216
217void MediaLog::SetDoubleProperty(
218    const char* key, double value) {
219  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
220  event->params.SetDouble(key, value);
221  AddEvent(event.Pass());
222}
223
224void MediaLog::SetBooleanProperty(
225    const char* key, bool value) {
226  scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
227  event->params.SetBoolean(key, value);
228  AddEvent(event.Pass());
229}
230
231}  //namespace media
232