功能:沿用Android cmds下的screenrecord代码,整理成可以供native程序调用的一个可以获取实时screen h264码流的一个库,分享一下!!
头文件screenrecord.h
#include <stdint.h>
class IScreenRecordCallback
{
public:
virtual ~IScreenRecordCallback(){}
virtual void onData(void* pData, size_t size) = 0;
//virtual void onCodecConfig(void* pData, size_t size) = 0;
};
class ScreenRecordImp;
class ScreenRecord
{
public:
ScreenRecord();
~ScreenRecord();
int start(IScreenRecordCallback* callback);
void stop();
private:
ScreenRecordImp* m_pImp;
};
实现文件:screenrecord.cpp
#include "screenrecord.h"
#include <iostream>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <utils/Errors.h>
#include <utils/Thread.h>
#include <utils/Timers.h>
#include <media/openmax/OMX_IVCommon.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/ISurfaceComposer.h>
#include <ui/DisplayInfo.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaCodec.h>
#include <media/stagefright/MediaErrors.h>
#include <media/ICrypto.h>
#include <utils/Errors.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <getopt.h>
#include <sys/wait.h>
using namespace android;
using namespace std;
#define LOG_TAG "LibScreenRecord"
//#define LOG_NDEBUG 0
static const uint32_t kFallbackWidth = 1280; // 720p
static const uint32_t kFallbackHeight = 720;
class ScreenRecordImp
{
public:
ScreenRecordImp();
int start(IScreenRecordCallback* callback);
void stop();
private:
bool isDeviceRotated(int orientation);
status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec,
sp<IGraphicBufferProducer>* pBufferProducer);
status_t prepareVirtualDisplay(const DisplayInfo& mainDpyInfo,
const sp<IGraphicBufferProducer>& bufferProducer,
sp<IBinder>* pDisplayHandle);
status_t setDisplayProjection(const sp<IBinder>& dpy,
const DisplayInfo& mainDpyInfo);
status_t runEncoder(const sp<MediaCodec>& encoder, IScreenRecordCallback* callback, sp<IBinder>& mainDpy, sp<IBinder>& dpy, uint8_t orientation);
private:
bool mRotate; // rotate 90 degrees
//bool mSizeSpecified; // was size explicitly requested?
uint32_t mVideoWidth; // default width+height
uint32_t mVideoHeight;
uint32_t mBitRate;
//uint32_t mTimeLimitSec;
bool mStopRequested;
};
ScreenRecord::ScreenRecord()
{
m_pImp = new ScreenRecordImp;
}
ScreenRecord::~ScreenRecord()
{
stop();
delete m_pImp;
m_pImp = NULL;
}
int ScreenRecord::start(IScreenRecordCallback* callback)
{
return m_pImp->start(callback);
}
void ScreenRecord::stop()
{
m_pImp->stop();
}
ScreenRecordImp::ScreenRecordImp():mRotate(false),
mVideoWidth(0),
mVideoHeight(0),
mBitRate(4000000), // 4Mbp
mStopRequested(true)
{
}
bool ScreenRecordImp::isDeviceRotated(int orientation) {
return orientation != DISPLAY_ORIENTATION_0 &&
orientation != DISPLAY_ORIENTATION_180;
}
status_t ScreenRecordImp::setDisplayProjection(const sp<IBinder>& dpy,
const DisplayInfo& mainDpyInfo) {
status_t err;
// Set the region of the layer stack we're interested in, which in our
// case is "all of it". If the app is rotated (so that the width of the
// app is based on the height of the display), reverse width/height.
bool deviceRotated = isDeviceRotated(mainDpyInfo.orientation);
uint32_t sourceWidth, sourceHeight;
if (!deviceRotated) {
sourceWidth = mainDpyInfo.w;
sourceHeight = mainDpyInfo.h;
} else {
ALOGV("using rotated width/height");
sourceHeight = mainDpyInfo.w;
sourceWidth = mainDpyInfo.h;
}
Rect layerStackRect(sourceWidth, sourceHeight);
// We need to preserve the aspect ratio of the display.
float displayAspect = (float) sourceHeight / (float) sourceWidth;
// Set the way we map the output onto the display surface (which will
// be e.g. 1280x720 for a 720p video). The rect is interpreted
// post-rotation, so if the displa