// 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.
#include "media/base/media_log.h"
#include <string>
#include "base/atomic_sequence_num.h"
#include "base/logging.h"
#include "base/values.h"
namespace media {
// A count of all MediaLogs created in the current process. Used to generate
// unique IDs.
static base::StaticAtomicSequenceNumber g_media_log_count;
const char* MediaLog::EventTypeToString(MediaLogEvent::Type type) {
switch (type) {
case MediaLogEvent::WEBMEDIAPLAYER_CREATED:
return "WEBMEDIAPLAYER_CREATED";
case MediaLogEvent::WEBMEDIAPLAYER_DESTROYED:
return "WEBMEDIAPLAYER_DESTROYED";
case MediaLogEvent::PIPELINE_CREATED:
return "PIPELINE_CREATED";
case MediaLogEvent::PIPELINE_DESTROYED:
return "PIPELINE_DESTROYED";
case MediaLogEvent::LOAD:
return "LOAD";
case MediaLogEvent::SEEK:
return "SEEK";
case MediaLogEvent::PLAY:
return "PLAY";
case MediaLogEvent::PAUSE:
return "PAUSE";
case MediaLogEvent::PIPELINE_STATE_CHANGED:
return "PIPELINE_STATE_CHANGED";
case MediaLogEvent::PIPELINE_ERROR:
return "PIPELINE_ERROR";
case MediaLogEvent::VIDEO_SIZE_SET:
return "VIDEO_SIZE_SET";
case MediaLogEvent::DURATION_SET:
return "DURATION_SET";
case MediaLogEvent::TOTAL_BYTES_SET:
return "TOTAL_BYTES_SET";
case MediaLogEvent::NETWORK_ACTIVITY_SET:
return "NETWORK_ACTIVITY_SET";
case MediaLogEvent::AUDIO_ENDED:
return "AUDIO_ENDED";
case MediaLogEvent::VIDEO_ENDED:
return "VIDEO_ENDED";
case MediaLogEvent::TEXT_ENDED:
return "TEXT_ENDED";
case MediaLogEvent::BUFFERED_EXTENTS_CHANGED:
return "BUFFERED_EXTENTS_CHANGED";
case MediaLogEvent::MEDIA_SOURCE_ERROR:
return "MEDIA_SOURCE_ERROR";
case MediaLogEvent::PROPERTY_CHANGE:
return "PROPERTY_CHANGE";
}
NOTREACHED();
return NULL;
}
const char* MediaLog::PipelineStatusToString(PipelineStatus status) {
switch (status) {
case PIPELINE_OK:
return "pipeline: ok";
case PIPELINE_ERROR_URL_NOT_FOUND:
return "pipeline: url not found";
case PIPELINE_ERROR_NETWORK:
return "pipeline: network error";
case PIPELINE_ERROR_DECODE:
return "pipeline: decode error";
case PIPELINE_ERROR_DECRYPT:
return "pipeline: decrypt error";
case PIPELINE_ERROR_ABORT:
return "pipeline: abort";
case PIPELINE_ERROR_INITIALIZATION_FAILED:
return "pipeline: initialization failed";
case PIPELINE_ERROR_COULD_NOT_RENDER:
return "pipeline: could not render";
case PIPELINE_ERROR_READ:
return "pipeline: read error";
case PIPELINE_ERROR_OPERATION_PENDING:
return "pipeline: operation pending";
case PIPELINE_ERROR_INVALID_STATE:
return "pipeline: invalid state";
case DEMUXER_ERROR_COULD_NOT_OPEN:
return "demuxer: could not open";
case DEMUXER_ERROR_COULD_NOT_PARSE:
return "dumuxer: could not parse";
case DEMUXER_ERROR_NO_SUPPORTED_STREAMS:
return "demuxer: no supported streams";
case DECODER_ERROR_NOT_SUPPORTED:
return "decoder: not supported";
}
NOTREACHED();
return NULL;
}
LogHelper::LogHelper(const LogCB& log_cb) : log_cb_(log_cb) {}
LogHelper::~LogHelper() {
if (log_cb_.is_null())
return;
log_cb_.Run(stream_.str());
}
MediaLog::MediaLog() : id_(g_media_log_count.GetNext()) {}
MediaLog::~MediaLog() {}
void MediaLog::AddEvent(scoped_ptr<MediaLogEvent> event) {}
scoped_ptr<MediaLogEvent> MediaLog::CreateEvent(MediaLogEvent::Type type) {
scoped_ptr<MediaLogEvent> event(new MediaLogEvent);
event->id = id_;
event->type = type;
event->time = base::TimeTicks::Now();
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateBooleanEvent(
MediaLogEvent::Type type, const char* property, bool value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(type));
event->params.SetBoolean(property, value);
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateStringEvent(
MediaLogEvent::Type type, const char* property, const std::string& value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(type));
event->params.SetString(property, value);
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateTimeEvent(
MediaLogEvent::Type type, const char* property, base::TimeDelta value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(type));
if (value.is_max())
event->params.SetString(property, "unknown");
else
event->params.SetDouble(property, value.InSecondsF());
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateLoadEvent(const std::string& url) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::LOAD));
event->params.SetString("url", url);
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateSeekEvent(float seconds) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::SEEK));
event->params.SetDouble("seek_target", seconds);
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreatePipelineStateChangedEvent(
Pipeline::State state) {
scoped_ptr<MediaLogEvent> event(
CreateEvent(MediaLogEvent::PIPELINE_STATE_CHANGED));
event->params.SetString("pipeline_state", Pipeline::GetStateString(state));
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreatePipelineErrorEvent(
PipelineStatus error) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PIPELINE_ERROR));
event->params.SetString("pipeline_error", PipelineStatusToString(error));
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateVideoSizeSetEvent(
size_t width, size_t height) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::VIDEO_SIZE_SET));
event->params.SetInteger("width", width);
event->params.SetInteger("height", height);
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateBufferedExtentsChangedEvent(
int64 start, int64 current, int64 end) {
scoped_ptr<MediaLogEvent> event(
CreateEvent(MediaLogEvent::BUFFERED_EXTENTS_CHANGED));
// These values are headed to JS where there is no int64 so we use a double
// and accept loss of precision above 2^53 bytes (8 Exabytes).
event->params.SetDouble("buffer_start", start);
event->params.SetDouble("buffer_current", current);
event->params.SetDouble("buffer_end", end);
return event.Pass();
}
scoped_ptr<MediaLogEvent> MediaLog::CreateMediaSourceErrorEvent(
const std::string& error) {
scoped_ptr<MediaLogEvent> event(
CreateEvent(MediaLogEvent::MEDIA_SOURCE_ERROR));
event->params.SetString("error", error);
return event.Pass();
}
void MediaLog::SetStringProperty(
const char* key, const std::string& value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
event->params.SetString(key, value);
AddEvent(event.Pass());
}
void MediaLog::SetIntegerProperty(
const char* key, int value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
event->params.SetInteger(key, value);
AddEvent(event.Pass());
}
void MediaLog::SetDoubleProperty(
const char* key, double value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
event->params.SetDouble(key, value);
AddEvent(event.Pass());
}
void MediaLog::SetBooleanProperty(
const char* key, bool value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
event->params.SetBoolean(key, value);
AddEvent(event.Pass());
}
void MediaLog::SetTimeProperty(
const char* key, base::TimeDelta value) {
scoped_ptr<MediaLogEvent> event(CreateEvent(MediaLogEvent::PROPERTY_CHANGE));
if (value.is_max())
event->params.SetString(key, "unknown");
else
event->params.SetDouble(key, value.InSecondsF());
AddEvent(event.Pass());
}
} //namespace media