|
|
|
@ -139,14 +139,6 @@ static status_t configureSignals() {
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Returns "true" if the device is rotated 90 degrees.
|
|
|
|
|
*/
|
|
|
|
|
static bool isDeviceRotated(int orientation) {
|
|
|
|
|
return orientation != DISPLAY_ORIENTATION_0 &&
|
|
|
|
|
orientation != DISPLAY_ORIENTATION_180;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Configures and starts the MediaCodec encoder. Obtains an input surface
|
|
|
|
|
* from the codec.
|
|
|
|
@ -242,22 +234,11 @@ static status_t setDisplayProjection(
|
|
|
|
|
const DisplayInfo& mainDpyInfo) {
|
|
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
// case is "all of it".
|
|
|
|
|
Rect layerStackRect(mainDpyInfo.w, mainDpyInfo.h);
|
|
|
|
|
|
|
|
|
|
// We need to preserve the aspect ratio of the display.
|
|
|
|
|
float displayAspect = (float) sourceHeight / (float) sourceWidth;
|
|
|
|
|
float displayAspect = (float) mainDpyInfo.h / (float) mainDpyInfo.w;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Set the way we map the output onto the display surface (which will
|
|
|
|
@ -333,6 +314,22 @@ static status_t prepareVirtualDisplay(const DisplayInfo& mainDpyInfo,
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the main display width and height to the actual width and height
|
|
|
|
|
*/
|
|
|
|
|
static status_t getActualDisplaySize(const sp<IBinder>& mainDpy, DisplayInfo* mainDpyInfo) {
|
|
|
|
|
Rect viewport;
|
|
|
|
|
status_t err = SurfaceComposerClient::getDisplayViewport(mainDpy, &viewport);
|
|
|
|
|
if (err != NO_ERROR) {
|
|
|
|
|
fprintf(stderr, "ERROR: unable to get display viewport\n");
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
mainDpyInfo->w = viewport.width();
|
|
|
|
|
mainDpyInfo->h = viewport.height();
|
|
|
|
|
|
|
|
|
|
return NO_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Runs the MediaCodec encoder, sending the output to the MediaMuxer. The
|
|
|
|
|
* input frames are coming from the virtual display as fast as SurfaceFlinger
|
|
|
|
@ -403,14 +400,22 @@ static status_t runEncoder(const sp<MediaCodec>& encoder,
|
|
|
|
|
// useful stuff is hard to get at without a Dalvik VM.
|
|
|
|
|
err = SurfaceComposerClient::getDisplayInfo(mainDpy,
|
|
|
|
|
&mainDpyInfo);
|
|
|
|
|
if (err != NO_ERROR) {
|
|
|
|
|
if (err == NO_ERROR) {
|
|
|
|
|
err = getActualDisplaySize(mainDpy, &mainDpyInfo);
|
|
|
|
|
if (err != NO_ERROR) {
|
|
|
|
|
fprintf(stderr, "ERROR: unable to set actual display size\n");
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (orientation != mainDpyInfo.orientation) {
|
|
|
|
|
ALOGD("orientation changed, now %d", mainDpyInfo.orientation);
|
|
|
|
|
SurfaceComposerClient::Transaction t;
|
|
|
|
|
setDisplayProjection(t, virtualDpy, mainDpyInfo);
|
|
|
|
|
t.apply();
|
|
|
|
|
orientation = mainDpyInfo.orientation;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ALOGW("getDisplayInfo(main) failed: %d", err);
|
|
|
|
|
} else if (orientation != mainDpyInfo.orientation) {
|
|
|
|
|
ALOGD("orientation changed, now %d", mainDpyInfo.orientation);
|
|
|
|
|
SurfaceComposerClient::Transaction t;
|
|
|
|
|
setDisplayProjection(t, virtualDpy, mainDpyInfo);
|
|
|
|
|
t.apply();
|
|
|
|
|
orientation = mainDpyInfo.orientation;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -552,6 +557,10 @@ static FILE* prepareRawOutput(const char* fileName) {
|
|
|
|
|
return rawFp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline uint32_t floorToEven(uint32_t num) {
|
|
|
|
|
return num & ~1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Main "do work" start point.
|
|
|
|
|
*
|
|
|
|
@ -579,6 +588,13 @@ static status_t recordScreen(const char* fileName) {
|
|
|
|
|
fprintf(stderr, "ERROR: unable to get display characteristics\n");
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = getActualDisplaySize(mainDpy, &mainDpyInfo);
|
|
|
|
|
if (err != NO_ERROR) {
|
|
|
|
|
fprintf(stderr, "ERROR: unable to set actual display size\n");
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (gVerbose) {
|
|
|
|
|
printf("Main display is %dx%d @%.2ffps (orientation=%u)\n",
|
|
|
|
|
mainDpyInfo.w, mainDpyInfo.h, mainDpyInfo.fps,
|
|
|
|
@ -586,12 +602,12 @@ static status_t recordScreen(const char* fileName) {
|
|
|
|
|
fflush(stdout);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rotated = isDeviceRotated(mainDpyInfo.orientation);
|
|
|
|
|
// Encoder can't take odd number as config
|
|
|
|
|
if (gVideoWidth == 0) {
|
|
|
|
|
gVideoWidth = rotated ? mainDpyInfo.h : mainDpyInfo.w;
|
|
|
|
|
gVideoWidth = floorToEven(mainDpyInfo.w);
|
|
|
|
|
}
|
|
|
|
|
if (gVideoHeight == 0) {
|
|
|
|
|
gVideoHeight = rotated ? mainDpyInfo.w : mainDpyInfo.h;
|
|
|
|
|
gVideoHeight = floorToEven(mainDpyInfo.h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Configure and start the encoder.
|
|
|
|
|