Bug 879668 - Part 4: Add OmxVideoTrackEncoder to file OmxTrackEncoder. r=roc

This commit is contained in:
Shelly Lin 2014-01-17 14:30:02 -05:00
parent 131af2cba3
commit fa29418b0a
4 changed files with 211 additions and 0 deletions

View File

@ -0,0 +1,13 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
# You can obtain one at http://mozilla.org/MPL/2.0/.
include $(topsrcdir)/config/rules.mk
# These includes are from Android JB, for use of MediaCodec.
INCLUDES += \
-I$(topsrcdir)/ipc/chromium/src \
-I$(ANDROID_SOURCE)/frameworks/native/opengl/include/ \
-I$(ANDROID_SOURCE)/frameworks/native/include/ \
-I$(ANDROID_SOURCE)/frameworks/av/include/media/ \
$(NULL)

View File

@ -0,0 +1,150 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "OmxTrackEncoder.h"
#include "OMXCodecWrapper.h"
#include "VideoUtils.h"
#include "ISOTrackMetadata.h"
#ifdef MOZ_WIDGET_GONK
#include <android/log.h>
#define OMX_LOG(args...) \
do { \
__android_log_print(ANDROID_LOG_INFO, "OmxTrackEncoder", ##args); \
} while (0)
#else
#define OMX_LOG(args, ...)
#endif
using namespace android;
namespace mozilla {
#define ENCODER_CONFIG_FRAME_RATE 30 // fps
#define GET_ENCODED_VIDEO_FRAME_TIMEOUT 100000 // microseconds
nsresult
OmxVideoTrackEncoder::Init(int aWidth, int aHeight, TrackRate aTrackRate)
{
mFrameWidth = aWidth;
mFrameHeight = aHeight;
mTrackRate = aTrackRate;
mEncoder = OMXCodecWrapper::CreateAVCEncoder();
NS_ENSURE_TRUE(mEncoder, NS_ERROR_FAILURE);
nsresult rv = mEncoder->Configure(mFrameWidth, mFrameHeight,
ENCODER_CONFIG_FRAME_RATE);
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
mInitialized = (rv == NS_OK);
mReentrantMonitor.NotifyAll();
return rv;
}
already_AddRefed<TrackMetadataBase>
OmxVideoTrackEncoder::GetMetadata()
{
{
// Wait if mEncoder is not initialized nor is being canceled.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
while (!mCanceled && !mInitialized) {
mReentrantMonitor.Wait();
}
}
if (mCanceled || mEncodingComplete) {
return nullptr;
}
nsRefPtr<AVCTrackMetadata> meta = new AVCTrackMetadata();
meta->Width = mFrameWidth;
meta->Height = mFrameHeight;
meta->FrameRate = ENCODER_CONFIG_FRAME_RATE;
meta->VideoFrequency = 90000; // Hz
return meta.forget();
}
nsresult
OmxVideoTrackEncoder::GetEncodedTrack(EncodedFrameContainer& aData)
{
VideoSegment segment;
{
// Move all the samples from mRawSegment to segment. We only hold the
// monitor in this block.
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
// Wait if mEncoder is not initialized nor is being canceled.
while (!mCanceled && (!mInitialized ||
(mRawSegment.GetDuration() == 0 && !mEndOfStream))) {
mReentrantMonitor.Wait();
}
if (mCanceled || mEncodingComplete) {
return NS_ERROR_FAILURE;
}
segment.AppendFrom(&mRawSegment);
}
// Start queuing raw frames to the input buffers of OMXCodecWrapper.
VideoSegment::ChunkIterator iter(segment);
while (!iter.IsEnded()) {
VideoChunk chunk = *iter;
// Send only the unique video frames to OMXCodecWrapper.
if (mLastFrame != chunk.mFrame) {
uint64_t totalDurationUs = mTotalFrameDuration * USECS_PER_S / mTrackRate;
layers::Image* img = (chunk.IsNull() || chunk.mFrame.GetForceBlack()) ?
nullptr : chunk.mFrame.GetImage();
mEncoder->Encode(img, mFrameWidth, mFrameHeight, totalDurationUs);
}
mLastFrame.TakeFrom(&chunk.mFrame);
mTotalFrameDuration += chunk.GetDuration();
iter.Next();
}
// Send the EOS signal to OMXCodecWrapper.
if (mEndOfStream && iter.IsEnded() && !mEosSetInEncoder) {
mEosSetInEncoder = true;
uint64_t totalDurationUs = mTotalFrameDuration * USECS_PER_S / mTrackRate;
layers::Image* img = (!mLastFrame.GetImage() || mLastFrame.GetForceBlack())
? nullptr : mLastFrame.GetImage();
mEncoder->Encode(img, mFrameWidth, mFrameHeight, totalDurationUs,
OMXCodecWrapper::BUFFER_EOS);
}
// Dequeue an encoded frame from the output buffers of OMXCodecWrapper.
nsTArray<uint8_t> buffer;
int outFlags = 0;
int64_t outTimeStampUs = 0;
mEncoder->GetNextEncodedFrame(&buffer, &outTimeStampUs, &outFlags,
GET_ENCODED_VIDEO_FRAME_TIMEOUT);
if (!buffer.IsEmpty()) {
nsRefPtr<EncodedFrame> videoData = new EncodedFrame();
if (outFlags & OMXCodecWrapper::BUFFER_CODEC_CONFIG) {
videoData->SetFrameType(EncodedFrame::AVC_CSD);
} else {
videoData->SetFrameType((outFlags & OMXCodecWrapper::BUFFER_SYNC_FRAME) ?
EncodedFrame::I_FRAME : EncodedFrame::P_FRAME);
}
videoData->SetFrameData(&buffer);
videoData->SetTimeStamp(outTimeStampUs);
aData.AppendEncodedFrame(videoData);
}
if (outFlags & OMXCodecWrapper::BUFFER_EOS) {
mEncodingComplete = true;
OMX_LOG("Done encoding video.");
}
return NS_OK;
}
}

View File

@ -0,0 +1,44 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef OmxTrackEncoder_h_
#define OmxTrackEncoder_h_
#include "TrackEncoder.h"
namespace android {
class OMXVideoEncoder;
}
/**
* There are two major classes defined in file OmxTrackEncoder;
* OmxVideoTrackEncoder and OmxAudioTrackEncoder, the video and audio track
* encoder for media type AVC/h.264 and AAC. OMXCodecWrapper wraps and controls
* an instance of MediaCodec, defined in libstagefright, runs on Android Jelly
* Bean platform.
*/
namespace mozilla {
class OmxVideoTrackEncoder: public VideoTrackEncoder
{
public:
OmxVideoTrackEncoder()
: VideoTrackEncoder()
{}
already_AddRefed<TrackMetadataBase> GetMetadata() MOZ_OVERRIDE;
nsresult GetEncodedTrack(EncodedFrameContainer& aData) MOZ_OVERRIDE;
protected:
nsresult Init(int aWidth, int aHeight, TrackRate aTrackRate) MOZ_OVERRIDE;
private:
nsAutoPtr<android::OMXVideoEncoder> mEncoder;
};
}
#endif

View File

@ -26,7 +26,11 @@ if CONFIG['MOZ_OPUS']:
if CONFIG['MOZ_OMX_ENCODER']:
DEFINES['MOZ_OMX_ENCODER'] = True
EXPORTS += ['OmxTrackEncoder.h']
UNIFIED_SOURCES += ['OmxTrackEncoder.cpp']
FAIL_ON_WARNINGS = True
FINAL_LIBRARY = 'gklayout'
include('/ipc/chromium/chromium-config.mozbuild')