blob: 87379c3c9fd23771db3e4d01a0a1ec5ba02d932b [file] [log] [blame]
// Copyright (c) 2012 The WebM project authors. All Rights Reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file in the root of the source
// tree. An additional intellectual property rights grant can be found
// in the file PATENTS. All contributing project authors may
// be found in the AUTHORS file in the root of the source tree.
#include <memory>
#include <string>
#include <thread>
#include "encoder/audio_encoder.h"
#include "encoder/basictypes.h"
#include "encoder/buffer_pool.h"
#include "encoder/encoder_base.h"
#include "encoder/data_sink.h"
#include "encoder/video_encoder.h"
#include "encoder/vorbis_encoder.h"
namespace webmlive {
// All timestamps are in milliseconds.
const int kTimebase = 1000;
// Special value meaning use system default device.
const int kUseDefaultDevice = -1;
struct WebmEncoderConfig {
// User interface control structure. |MediaSourceImpl| will attempt to
// display configuration control dialogs when fields are set to true.
struct UserInterfaceOptions {
: manual_audio_config(false),
manual_video_config(false) {}
bool manual_audio_config; // Show audio source configuration interface.
bool manual_video_config; // Show video source configuration interface.
: disable_audio(false),
dash_start_number("1") {}
// Audio/Video disable flags.
bool disable_audio;
bool disable_video;
// Name of the audio device. Leave empty to use system default.
std::string audio_device_name;
// Audio device index. Leave set to |kUseDefaultDevice| to use system default.
int audio_device_index;
// Name of the video device. Leave empty to use system default.
std::string video_device_name;
// Video device index. Leave set to |kUseDefaultDevice| to use system default.
int video_device_index;
// Requested audio capture settings.
AudioConfig requested_audio_config;
// Actual audio capture settings.
AudioConfig actual_audio_config;
// Requested video capture settings.
VideoConfig requested_video_config;
// Actual video capture settings.
VideoConfig actual_video_config;
// Vorbis audio encoder settings.
VorbisConfig vorbis_config;
// VPx encoder settings.
VpxConfig vpx_config;
// Source device options.
UserInterfaceOptions ui_opts;
// Enable DASH encoding mode.
bool dash_encode;
// MPD name and DASH chunk ID prefix.
std::string dash_name;
// Output directory for MPD and DASH chunks.
std::string dash_dir;
// MPD SegmentTemplate startNumber value.
std::string dash_start_number;
class DashWriter;
class MediaSourceImpl;
class LiveWebmMuxer;
// Top level WebM encoder class. Manages capture from A/V input devices, VPx
// encoding, Vorbis encoding, and muxing into a WebM stream.
class WebmEncoder : public AudioSamplesCallbackInterface,
public VideoFrameCallbackInterface {
// Default size of |chunk_buffer_|.
static const int kDefaultChunkBufferSize = 100 * 1024;
enum {
// Data sink write failed.
kDataSinkWriteFail = -117,
// AV capture implementation unable to setup audio buffer sink.
kAudioSinkError = -116,
// AV capture source stopped on its own.
kAVCaptureStopped = -115,
// AV capture implementation unable to setup video frame sink.
kVideoSinkError = -114,
// Encoder implementation unable to configure audio source.
kAudioConfigureError = -113,
// Encoder implementation unable to configure video source.
kVideoConfigureError = -112,
// Encoder implementation unable to monitor encoder state.
kEncodeMonitorError = -111,
// Encoder implementation unable to control encoder.
kEncodeControlError = -110,
// Encoder implementation file writing related error.
kFileWriteError = -109,
// Encoder implementation WebM muxing related error.
kWebmMuxerError = -108,
// Encoder implementation audio encoding related error.
kAudioEncoderError = -107,
// Encoder implementation video encoding related error.
kVideoEncoderError = -106,
// Invalid argument passed to method.
kInvalidArg = -105,
// Operation not implemented.
kNotImplemented = -104,
// Unable to find an audio source.
kNoAudioSource = -103,
// Unable to find a video source.
kNoVideoSource = -102,
// Encoder implementation initialization failed.
kInitFailed = -101,
// Cannot run the encoder.
kRunFailed = -100,
kNoMemory = -2,
kInvaligArg = -1,
kSuccess = 0,
~WebmEncoder() override;
// Initializes the encoder. Returns |kSuccess| upon success, or one of the
// above status codes upon failure. Always returns |kInvalidArg| when
// |ptr_data_sink| is NULL.
int Init(const WebmEncoderConfig& config, DataSink* ptr_data_sink);
// Runs the encoder. Returns |kSuccess| when successful, or one of the above
// status codes upon failure.
int Run();
// Stops the encoder.
void Stop();
// Returns encoded duration in milliseconds.
int64 encoded_duration() const;
// Returns |WebmEncoderConfig| with fields set to default values.
static WebmEncoderConfig DefaultConfig();
WebmEncoderConfig config() const { return config_; }
// |AudioSamplesCallbackInterface| methods
// Method used by |MediaSourceImpl| to push audio buffers into encoding
// threads.
bool OnSamplesReceived(AudioBuffer* ptr_buffer) override;
// |VideoFrameCallbackInterface| methods
// Method used by |MediaSourceImpl| to push video frames into encoding
// threads.
int OnVideoFrameReceived(VideoFrame* ptr_frame) override;
// Function pointer type used for indirect access to the encoder loop
// methods from |EncoderThread()|.
typedef int (WebmEncoder::*EncoderLoopFunc)();
// Returns true when user wants the encode thread to stop.
bool StopRequested();
// Reads chunk from |muxer| and reallocates |chunk_buffer_| when necessary.
// Returns true when successful.
bool ReadChunkFromMuxer(std::unique_ptr<LiveWebmMuxer>* muxer,
int32 chunk_length);
// Encoding thread function.
void EncoderThread();
// Audio/Video |EncoderLoopFunc|s. Called by |EncoderThread()| via
// |ptr_encode_func_|. All loop functions return |kSuccess| when the encode
// pass succeeds.
int EncodeAudioOnly();
int AVEncode();
int EncodeVideoFrame();
int DashEncode();
// Utility function used to encode a single audio input buffer.
int EncodeAudioBuffer();
// Waits for input samples from |ptr_media_source_| and sets
// |timestamp_offset_| when one or both streams start with a negative
// timestamp.
int WaitForSamples();
// Returns the timestamp of the next available video frame via |timestamp|.
int PeekVideoTimestamp(int64* timestamp);
// Writes |muxer| chunk to |ptr_data_sink_| when |muxer->ChunkReady()|
// returns true.
int WriteMuxerChunkToDataSink(std::unique_ptr<LiveWebmMuxer>* muxer);
// Writes last chunk from |muxer| to |ptr_data_sink_| and finalizes |muxer|.
int WriteLastMuxerChunkToDataSink(std::unique_ptr<LiveWebmMuxer>* muxer);
// Returns a chunk identifier for |chunk_num| from |muxer|.
std::string NextChunkId(const std::string& muxer_id,
int64 chunk_num) const;
// Set to true when |Init()| is successful.
bool initialized_;
// Flag protected by |mutex_| and used by |EncoderThread()| via
// |StopRequested()| to determine when to terminate.
bool stop_;
// Temporary storage for chunks about to be passed to |ptr_data_sink_|.
std::unique_ptr<uint8[]> chunk_buffer_;
int32 chunk_buffer_size_;
// Pointer to platform specific audio/video source object implementation.
std::unique_ptr<MediaSourceImpl> ptr_media_source_;
// Pointer to live WebM muxer. |ptr_muxer_| is used for muxed A/V output and
// single stream output.
std::unique_ptr<LiveWebmMuxer> ptr_muxer_;
// Pointers to live WebM muxers. |ptr_muxer_aud_| and |ptr_muxer_vid_| are
// used for DASH encodes that do not mux audio and video into the same WebM
// chunks.
// TODO(tomfinegan): Support multiple streams of each media type.
std::unique_ptr<LiveWebmMuxer> ptr_muxer_aud_;
std::unique_ptr<LiveWebmMuxer> ptr_muxer_vid_;
// Mutex providing synchronization between user interface and encoder thread.
mutable std::mutex mutex_;
// Encoder thread object.
std::shared_ptr<std::thread> encode_thread_;
// Data sink to which WebM chunks are written.
DataSink* ptr_data_sink_;
// Buffer object used to push |VideoFrame|s from |MediaSourceImpl| into
// |EncoderThread()|.
BufferPool<VideoFrame> video_pool_;
// Most recent frame from |video_pool_|.
VideoFrame raw_frame_;
// Most recent frame from |video_encoder_|.
VideoFrame vpx_frame_;
// Video encoder.
VideoEncoder video_encoder_;
// Encoded duration in milliseconds.
int64 encoded_duration_;
// Buffer object used to push |AudioBuffer|s from |MediaSourceImpl| into
// |EncoderThread()|.
BufferPool<AudioBuffer> audio_pool_;
// Most recent uncompressed audio buffer from |audio_pool_|.
AudioBuffer raw_audio_buffer_;
// Most recent vorbis audio buffer from |vorbis_encoder_|.
AudioBuffer vorbis_audio_buffer_;
// Vorbis encoder object.
VorbisEncoder vorbis_encoder_;
// Encoder configuration.
WebmEncoderConfig config_;
// Encoder loop function pointer.
EncoderLoopFunc ptr_encode_func_;
// DASH manifest writer.
std::unique_ptr<DashWriter> dash_writer_;
// Timestamp adjustment value. Expressed in milliseconds. Used to change
// input buffer timestamps when a stream starts with a timestamp less than 0.
int64 timestamp_offset_;
} // namespace webmlive