diff options
author | ivankr@chromium.org <ivankr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-24 01:47:34 +0000 |
---|---|---|
committer | ivankr@chromium.org <ivankr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-24 01:47:34 +0000 |
commit | 129f2869aca4cdffb14f09c9bcc3d49f087b564d (patch) | |
tree | 2f2422ee8cedbceeadfe4cc7b3e1f8f540d41384 /media/webm | |
parent | 13d6b3c13a2948b2da99c4f1ba49649653b7483a (diff) | |
download | chromium_src-129f2869aca4cdffb14f09c9bcc3d49f087b564d.zip chromium_src-129f2869aca4cdffb14f09c9bcc3d49f087b564d.tar.gz chromium_src-129f2869aca4cdffb14f09c9bcc3d49f087b564d.tar.bz2 |
Revert 148024 - [cros] Implement WebM encoder/muxer for animated avatar capture.
BUG=132423
TEST=None
Review URL: https://chromiumcodereview.appspot.com/10784037
TBR=ivankr@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10809068
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148027 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/webm')
-rw-r--r-- | media/webm/chromeos/DEPS | 4 | ||||
-rw-r--r-- | media/webm/chromeos/ebml_writer.cc | 27 | ||||
-rw-r--r-- | media/webm/chromeos/ebml_writer.h | 18 | ||||
-rw-r--r-- | media/webm/chromeos/webm_encoder.cc | 318 | ||||
-rw-r--r-- | media/webm/chromeos/webm_encoder.h | 98 |
5 files changed, 0 insertions, 465 deletions
diff --git a/media/webm/chromeos/DEPS b/media/webm/chromeos/DEPS deleted file mode 100644 index a4378dc..0000000 --- a/media/webm/chromeos/DEPS +++ /dev/null @@ -1,4 +0,0 @@ -include_rules = [ - "+libyuv", - "+third_party/libvpx", -] diff --git a/media/webm/chromeos/ebml_writer.cc b/media/webm/chromeos/ebml_writer.cc deleted file mode 100644 index 0da2bc2..0000000 --- a/media/webm/chromeos/ebml_writer.cc +++ /dev/null @@ -1,27 +0,0 @@ -// 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/webm/chromeos/ebml_writer.h" - -#include "media/base/media_export.h" - -extern "C" { -#include "third_party/libvpx/source/libvpx/libmkv/EbmlWriter.h" - -// These functions must be in the global namespace and visible to libmkv. - -void MEDIA_EXPORT Ebml_Write(EbmlGlobal* glob, - const void* buffer, - unsigned long len) { - glob->write_cb.Run(buffer, len); -} - -void MEDIA_EXPORT Ebml_Serialize(EbmlGlobal* glob, - const void* buffer, - int buffer_size, - unsigned long len) { - glob->serialize_cb.Run(buffer, buffer_size, len); -} - -} // extern "C" diff --git a/media/webm/chromeos/ebml_writer.h b/media/webm/chromeos/ebml_writer.h deleted file mode 100644 index cbc8b73..0000000 --- a/media/webm/chromeos/ebml_writer.h +++ /dev/null @@ -1,18 +0,0 @@ -// 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. - -#ifndef MEDIA_WEBM_CHROMEOS_EBML_WRITER_H_ -#define MEDIA_WEBM_CHROMEOS_EBML_WRITER_H_ - -#include "base/callback.h" - -// This struct serves as a bridge betweeen static libmkv interface and Chrome's -// base::Callback. Must be in the global namespace. See EbmlWriter.h. -struct EbmlGlobal { - base::Callback<void(const void* buffer, unsigned long len)> write_cb; - base::Callback<void(const void* buffer, int buffer_size, unsigned long len)> - serialize_cb; -}; - -#endif // MEDIA_WEBM_CHROMEOS_EBML_WRITER_H_ diff --git a/media/webm/chromeos/webm_encoder.cc b/media/webm/chromeos/webm_encoder.cc deleted file mode 100644 index 18ee194..0000000 --- a/media/webm/chromeos/webm_encoder.cc +++ /dev/null @@ -1,318 +0,0 @@ -// 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/webm/chromeos/webm_encoder.h" - -#include "base/bind.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/memory/scoped_generic_obj.h" -#include "libyuv/convert.h" -#include "libyuv/video_common.h" -#include "third_party/skia/include/core/SkBitmap.h" - -extern "C" { -// Getting the right degree of C compatibility has been a constant struggle. -// - Stroustrup, C++ Report, 12(7), July/August 2000. -#define private priv -#include "third_party/libvpx/source/libvpx/libmkv/EbmlIDs.h" -#include "third_party/libvpx/source/libvpx/libmkv/EbmlWriter.h" -#undef private -} - -// Number of encoder threads to use. -static const int kNumEncoderThreads = 2; - -// Need a fixed size serializer for the track ID. libmkv provides a 64 bit -// one, but not a 32 bit one. -static void Ebml_SerializeUnsigned32(EbmlGlobal* ebml, - unsigned long class_id, - uint64_t value) { - uint8 size_serialized = 4 | 0x80; - Ebml_WriteID(ebml, class_id); - Ebml_Serialize(ebml, &size_serialized, sizeof(size_serialized), 1); - Ebml_Serialize(ebml, &value, sizeof(value), 4); -} - -// Wrapper functor for vpx_codec_destroy(). -class VpxCodecDestroyHelper { - public: - void operator()(vpx_codec_ctx_t* codec) { - vpx_codec_destroy(codec); - } -}; - -// Wrapper functor for vpx_img_free(). -class VpxImgFreeHelper { - public: - void operator()(vpx_image_t* image) { - vpx_img_free(image); - } -}; - -namespace media { - -namespace chromeos { - -WebmEncoder::WebmEncoder(const FilePath& output_path, - int bitrate, - bool realtime) - : bitrate_(bitrate), - deadline_(realtime ? VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY), - output_path_(output_path), - has_errors_(false) { - ebml_writer_.write_cb = base::Bind( - &WebmEncoder::EbmlWrite, base::Unretained(this)); - ebml_writer_.serialize_cb = base::Bind( - &WebmEncoder::EbmlSerialize, base::Unretained(this)); -} - -bool WebmEncoder::EncodeFromSprite(const SkBitmap& sprite, - int fps_n, - int fps_d) { - DCHECK(!sprite.isNull()); - DCHECK(!sprite.empty()); - - has_errors_ = false; - width_ = sprite.width(); - height_ = sprite.width(); - fps_.num = fps_n; - fps_.den = fps_d; - - // Sprite is tiled vertically. - size_t frame_count = sprite.height() / width_; - - vpx_image_t image; - vpx_img_alloc(&image, VPX_IMG_FMT_I420, width_, height_, 16); - // Ensure that image is freed after return. - ScopedGenericObj<vpx_image_t*, VpxImgFreeHelper> image_ptr(&image); - - const vpx_codec_iface_t* codec_iface = vpx_codec_vp8_cx(); - DCHECK(codec_iface); - vpx_codec_err_t ret = vpx_codec_enc_config_default(codec_iface, &config_, 0); - DCHECK_EQ(VPX_CODEC_OK, ret); - - config_.rc_target_bitrate = bitrate_; - config_.g_w = width_; - config_.g_h = height_; - config_.g_pass = VPX_RC_ONE_PASS; - config_.g_profile = 0; // Default profile. - config_.g_threads = kNumEncoderThreads; - config_.rc_min_quantizer = 0; - config_.rc_max_quantizer = 63; // Maximum possible range. - config_.g_timebase.num = fps_.den; - config_.g_timebase.den = fps_.num; - config_.kf_mode = VPX_KF_AUTO; // Auto key frames. - - vpx_codec_ctx_t codec; - ret = vpx_codec_enc_init(&codec, codec_iface, &config_, 0); - if (ret != VPX_CODEC_OK) - return false; - // Ensure that codec context is freed after return. - ScopedGenericObj<vpx_codec_ctx_t*, VpxCodecDestroyHelper> codec_ptr(&codec); - - SkAutoLockPixels lock_sprite(sprite); - - const uint8* src = reinterpret_cast<const uint8*>(sprite.getAddr32(0, 0)); - size_t src_frame_size = sprite.getSize(); - int crop_y = 0; - - if (!WriteWebmHeader()) - return false; - - for (size_t frame = 0; frame < frame_count && !has_errors_; ++frame) { - int res = libyuv::ConvertToI420( - src, src_frame_size, - image.planes[VPX_PLANE_Y], image.stride[VPX_PLANE_Y], - image.planes[VPX_PLANE_U], image.stride[VPX_PLANE_U], - image.planes[VPX_PLANE_V], image.stride[VPX_PLANE_V], - 0, crop_y, // src origin - width_, sprite.height(), // src size - width_, height_, // dest size - libyuv::kRotate0, - libyuv::FOURCC_ARGB); - if (res) { - has_errors_ = true; - break; - } - crop_y += height_; - - ret = vpx_codec_encode(&codec, &image, frame, 1, 0, deadline_); - if (ret != VPX_CODEC_OK) { - has_errors_ = true; - break; - } - - vpx_codec_iter_t iter = NULL; - const vpx_codec_cx_pkt_t* packet; - while (!has_errors_ && (packet = vpx_codec_get_cx_data(&codec, &iter))) { - if (packet->kind == VPX_CODEC_CX_FRAME_PKT) - WriteWebmBlock(packet); - } - } - - return WriteWebmFooter(); -} - -bool WebmEncoder::WriteWebmHeader() { - output_ = file_util::OpenFile(output_path_, "wb"); - if (!output_) - return false; - - // Global header. - StartSubElement(EBML); - { - Ebml_SerializeUnsigned(&ebml_writer_, EBMLVersion, 1); - Ebml_SerializeUnsigned(&ebml_writer_, EBMLReadVersion, 1); - Ebml_SerializeUnsigned(&ebml_writer_, EBMLMaxIDLength, 4); - Ebml_SerializeUnsigned(&ebml_writer_, EBMLMaxSizeLength, 8); - Ebml_SerializeString(&ebml_writer_, DocType, "webm"); - Ebml_SerializeUnsigned(&ebml_writer_, DocTypeVersion, 2); - Ebml_SerializeUnsigned(&ebml_writer_, DocTypeReadVersion, 2); - } - EndSubElement(); // EBML - - // Single segment with a video track. - StartSubElement(Segment); - { - StartSubElement(Info); - { - // All timecodes in the segment will be expressed in milliseconds. - Ebml_SerializeUnsigned(&ebml_writer_, TimecodeScale, 1000000); - } - EndSubElement(); // Info - - StartSubElement(Tracks); - { - StartSubElement(TrackEntry); - { - Ebml_SerializeUnsigned(&ebml_writer_, TrackNumber, 1); - Ebml_SerializeUnsigned32(&ebml_writer_, TrackUID, 1); - Ebml_SerializeUnsigned(&ebml_writer_, TrackType, 1); // Video - Ebml_SerializeString(&ebml_writer_, CodecID, "V_VP8"); - - StartSubElement(Video); - { - Ebml_SerializeUnsigned(&ebml_writer_, PixelWidth, width_); - Ebml_SerializeUnsigned(&ebml_writer_, PixelHeight, height_); - Ebml_SerializeUnsigned(&ebml_writer_, StereoMode, 0); // Mono - float fps = static_cast<float>(fps_.num) / fps_.den; - Ebml_SerializeFloat(&ebml_writer_, FrameRate, fps); - } - EndSubElement(); // Video - } - EndSubElement(); // TrackEntry - } - EndSubElement(); // Tracks - - StartSubElement(Cluster); { - Ebml_SerializeUnsigned(&ebml_writer_, Timecode, 0); - } // Cluster left open. - } // Segment left open. - - // No check for |has_errors_| here because |false| is only returned when - // opening file fails. - return true; -} - -void WebmEncoder::WriteWebmBlock(const vpx_codec_cx_pkt_t* packet) { - bool is_keyframe = packet->data.frame.flags & VPX_FRAME_IS_KEY; - int64_t pts_ms = 1000 * packet->data.frame.pts * fps_.den / fps_.num; - - DVLOG(1) << "Video packet @" << pts_ms << " ms " - << packet->data.frame.sz << " bytes " - << (is_keyframe ? "K" : ""); - - Ebml_WriteID(&ebml_writer_, SimpleBlock); - - uint32 block_length = (packet->data.frame.sz + 4) | 0x10000000; - EbmlSerializeHelper(&block_length, 4); - - uint8 track_number = 1 | 0x80; - EbmlSerializeHelper(&track_number, 1); - - EbmlSerializeHelper(&pts_ms, 2); - - uint8 flags = 0; - if (is_keyframe) - flags |= 0x80; - if (packet->data.frame.flags & VPX_FRAME_IS_INVISIBLE) - flags |= 0x08; - EbmlSerializeHelper(&flags, 1); - - EbmlWrite(packet->data.frame.buf, packet->data.frame.sz); -} - -bool WebmEncoder::WriteWebmFooter() { - EndSubElement(); // Cluster - EndSubElement(); // Segment - DCHECK(ebml_sub_elements_.empty()); - return file_util::CloseFile(output_) && !has_errors_; -} - -void WebmEncoder::StartSubElement(unsigned long class_id) { - Ebml_WriteID(&ebml_writer_, class_id); - ebml_sub_elements_.push(ftell(output_)); - static const uint64_t kUnknownLen = 0x01FFFFFFFFFFFFFFLLU; - EbmlSerializeHelper(&kUnknownLen, 8); -} - -void WebmEncoder::EndSubElement() { - DCHECK(!ebml_sub_elements_.empty()); - - long int end_pos = ftell(output_); - long int start_pos = ebml_sub_elements_.top(); - ebml_sub_elements_.pop(); - - uint64_t size = (end_pos - start_pos - 8) | 0x0100000000000000ULL; - // Seek to the beginning of the sub-element and patch in the calculated size. - if (fseek(output_, start_pos, SEEK_SET)) { - has_errors_ = true; - LOG(ERROR) << "Error writing to " << output_path_.value(); - } - EbmlSerializeHelper(&size, 8); - - // Restore write position. - if (fseek(output_, end_pos, SEEK_SET)) { - has_errors_ = true; - LOG(ERROR) << "Error writing to " << output_path_.value(); - } -} - -void WebmEncoder::EbmlWrite(const void* buffer, - unsigned long len) { - if (fwrite(buffer, 1, len, output_) != len) { - has_errors_ = true; - LOG(ERROR) << "Error writing to " << output_path_.value(); - } -} - -template <class T> -void WebmEncoder::EbmlSerializeHelper(const T* buffer, unsigned long len) { - for (int i = len - 1; i >= 0; i--) { - uint8 c = *buffer >> (i * CHAR_BIT); - EbmlWrite(&c, 1); - } -} - -void WebmEncoder::EbmlSerialize(const void* buffer, - int buffer_size, - unsigned long len) { - switch (buffer_size) { - case 1: - return EbmlSerializeHelper(static_cast<const int8_t*>(buffer), len); - case 2: - return EbmlSerializeHelper(static_cast<const int16_t*>(buffer), len); - case 4: - return EbmlSerializeHelper(static_cast<const int32_t*>(buffer), len); - case 8: - return EbmlSerializeHelper(static_cast<const int64_t*>(buffer), len); - default: - NOTREACHED() << "Invalid EbmlSerialize length: " << len; - } -} - -} // namespace chromeos - -} // namespace media diff --git a/media/webm/chromeos/webm_encoder.h b/media/webm/chromeos/webm_encoder.h deleted file mode 100644 index 86c584a..0000000 --- a/media/webm/chromeos/webm_encoder.h +++ /dev/null @@ -1,98 +0,0 @@ -// 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. - -#ifndef MEDIA_WEBM_CHROMEOS_WEBM_ENCODER_H_ -#define MEDIA_WEBM_CHROMEOS_WEBM_ENCODER_H_ - -#include <stack> -#include <stdio.h> - -#include "base/file_path.h" -#include "media/base/media_export.h" -#include "media/webm/chromeos/ebml_writer.h" - -extern "C" { -#define VPX_CODEC_DISABLE_COMPAT 1 -#include "third_party/libvpx/libvpx.h" -} - -class FilePath; -class SkBitmap; - -namespace media { - -namespace chromeos { - -// WebM encoder using libvpx. Currently only supports one-pass, constant bitrate -// encoding of short files consisting of a single video track. Seek info and -// cues are not supported, so generated .webm file does not strictly adhere to -// WebM standard (http://www.webmproject.org/code/specs/container/). -class MEDIA_EXPORT WebmEncoder { - public: - // Create new instance for writing to |output_path|. If |realtime| is |true|, - // uses realtime deadline, otherwise - "good quality" deadline. - WebmEncoder(const FilePath& output_path, int bitrate, bool realtime); - - // Encodes video from a Nx(N*M) sprite, having M frames of size NxN with FPS - // |fps_n/fps_d|. Must be called on a thread that allows disk IO. - // Returns |true| iff encoding and writing to file is successful. - bool EncodeFromSprite(const SkBitmap& sprite, int fps_n, int fps_d); - - private: - // Writes global WebM header and starts a single video track. Returns |false| - // if there was an error opening file for writing. - bool WriteWebmHeader(); - - // Writes VPX packet to output file. - void WriteWebmBlock(const vpx_codec_cx_pkt_t* packet); - - // Finishes video track and closes output file. Returns |false| if there were - // any error during encoding/writing file. - bool WriteWebmFooter(); - - // Starts a new WebM sub-element of given type. Those can be nested. - void StartSubElement(unsigned long class_id); - - // Closes current top-level sub-element. - void EndSubElement(); - - // libmkv callbacks. - void EbmlWrite(const void* buffer, unsigned long len); - void EbmlSerialize(const void* buffer, int buffer_size, unsigned long len); - - template <typename T> - void EbmlSerializeHelper(const T* buffer, unsigned long len); - - // Video dimensions and FPS. - size_t width_; - size_t height_; - vpx_rational_t fps_; - - // VPX config in use. - vpx_codec_enc_cfg_t config_; - - // VPX parameters. - int bitrate_; - unsigned long deadline_; - - // EbmlWriter context. - EbmlGlobal ebml_writer_; - - // Stack with start offsets of currently open sub-elements. - std::stack<long int> ebml_sub_elements_; - - FilePath output_path_; - FILE* output_; - - // True if an error occured while encoding/writing to file. - bool has_errors_; - - DISALLOW_COPY_AND_ASSIGN(WebmEncoder); -}; - -} // namespace chromeos - -} // namespace media - -#endif // MEDIA_WEBM_CHROMEOS_WEBM_ENCODER_H_ |