screenrecord.cpp revision c475546b6df3b8febc0191e5895f4546a0abd52f
11ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni/*
21ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni * Copyright 2013 The Android Open Source Project
3da0f069871343119251d6b0586be356dc2146a62Yang Ni *
4433558f0f9abbf07770db288183a15fd261cace2Yabin Cui * Licensed under the Apache License, Version 2.0 (the "License");
5433558f0f9abbf07770db288183a15fd261cace2Yabin Cui * you may not use this file except in compliance with the License.
6433558f0f9abbf07770db288183a15fd261cace2Yabin Cui * You may obtain a copy of the License at
7da0f069871343119251d6b0586be356dc2146a62Yang Ni *
8062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni *      http://www.apache.org/licenses/LICENSE-2.0
9062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni *
10da0f069871343119251d6b0586be356dc2146a62Yang Ni * Unless required by applicable law or agreed to in writing, software
11da0f069871343119251d6b0586be356dc2146a62Yang Ni * distributed under the License is distributed on an "AS IS" BASIS,
12da0f069871343119251d6b0586be356dc2146a62Yang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da0f069871343119251d6b0586be356dc2146a62Yang Ni * See the License for the specific language governing permissions and
14da0f069871343119251d6b0586be356dc2146a62Yang Ni * limitations under the License.
15da0f069871343119251d6b0586be356dc2146a62Yang Ni */
16da0f069871343119251d6b0586be356dc2146a62Yang Ni
17da0f069871343119251d6b0586be356dc2146a62Yang Ni#define LOG_TAG "ScreenRecord"
181ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#define ATRACE_TAG ATRACE_TAG_GRAPHICS
191ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni//#define LOG_NDEBUG 0
201ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <utils/Log.h>
211ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
222abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni#include <binder/IPCThreadState.h>
231ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <utils/Errors.h>
241ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <utils/Timers.h>
251ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <utils/Trace.h>
26da0f069871343119251d6b0586be356dc2146a62Yang Ni
27da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <gui/Surface.h>
28da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <gui/SurfaceComposerClient.h>
29da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <gui/ISurfaceComposer.h>
301ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <ui/DisplayInfo.h>
311ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/openmax/OMX_IVCommon.h>
321ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/stagefright/foundation/ABuffer.h>
331ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/stagefright/foundation/AMessage.h>
341ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/stagefright/MediaCodec.h>
351ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/stagefright/MediaErrors.h>
36da0f069871343119251d6b0586be356dc2146a62Yang Ni#include <media/stagefright/MediaMuxer.h>
371ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <media/ICrypto.h>
381ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
391ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni#include <stdlib.h>
40ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni#include <unistd.h>
41eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <string.h>
42eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <stdio.h>
43eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <ctype.h>
44eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <fcntl.h>
45eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <signal.h>
46eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <getopt.h>
47eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <sys/wait.h>
48eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <termios.h>
49eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include <assert.h>
50eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
51eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include "screenrecord.h"
52eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni#include "Overlay.h"
53eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
54ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Niusing namespace android;
55ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
56eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic const uint32_t kMinBitRate = 100000;         // 0.1Mbps
57eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic const uint32_t kMaxBitRate = 200 * 1000000;  // 200Mbps
58eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic const uint32_t kMaxTimeLimitSec = 180;       // 3 minutes
59eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic const uint32_t kFallbackWidth = 1280;        // 720p
60eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic const uint32_t kFallbackHeight = 720;
61eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
62eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni// Command-line parameters.
63eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic bool gVerbose = false;           // chatty on stdout
64eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic bool gRotate = false;            // rotate 90 degrees
65eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic bool gRawOutput = false;         // generate raw H.264 byte stream output
661ffd86b448d78366190c540f98f8b6d641cdb6cfYang Nistatic bool gSizeSpecified = false;     // was size explicitly requested?
67eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic bool gWantInfoScreen = false;    // do we want initial info screen?
68eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic bool gWantFrameTime = false;     // do we want times on each frame?
691ffd86b448d78366190c540f98f8b6d641cdb6cfYang Nistatic uint32_t gVideoWidth = 0;        // default width+height
70eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic uint32_t gVideoHeight = 0;
71eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic uint32_t gBitRate = 4000000;     // 4Mbps
72eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic uint32_t gTimeLimitSec = kMaxTimeLimitSec;
73eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
74eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni// Set by signal handler to stop recording.
75eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic volatile bool gStopRequested;
76eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
771ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni// Previous signal handler state, restored after first hit.
78eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic struct sigaction gOrigSigactionINT;
791ffd86b448d78366190c540f98f8b6d641cdb6cfYang Nistatic struct sigaction gOrigSigactionHUP;
80eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
811ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
821ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni/*
83eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Catch keyboard interrupt signals.  On receipt, the "stop requested"
84eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * flag is raised, and the original handler is restored (so that, if
851ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni * we get stuck finishing, a second Ctrl-C will kill the process).
861ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni */
87da0f069871343119251d6b0586be356dc2146a62Yang Nistatic void signalCatcher(int signum)
88da0f069871343119251d6b0586be356dc2146a62Yang Ni{
89062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    gStopRequested = true;
90062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    switch (signum) {
91062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    case SIGINT:
92062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    case SIGHUP:
93062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        sigaction(SIGINT, &gOrigSigactionINT, NULL);
94da0f069871343119251d6b0586be356dc2146a62Yang Ni        sigaction(SIGHUP, &gOrigSigactionHUP, NULL);
95eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        break;
96eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    default:
97eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        abort();
98062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        break;
99da0f069871343119251d6b0586be356dc2146a62Yang Ni    }
100da0f069871343119251d6b0586be356dc2146a62Yang Ni}
101ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
102eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni/*
103eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Configures signal handlers.  The previous handlers are saved.
104eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni *
105da0f069871343119251d6b0586be356dc2146a62Yang Ni * If the command is run from an interactive adb shell, we get SIGINT
106ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni * when Ctrl-C is hit.  If we're run from the host, the local adb process
107ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni * gets the signal, and we get a SIGHUP when the terminal disconnects.
108062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni */
109eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic status_t configureSignals() {
110eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    struct sigaction act;
1111ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    memset(&act, 0, sizeof(act));
1121ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    act.sa_handler = signalCatcher;
113eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (sigaction(SIGINT, &act, &gOrigSigactionINT) != 0) {
114ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        status_t err = -errno;
115ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        fprintf(stderr, "Unable to configure SIGINT handler: %s\n",
116ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni                strerror(errno));
117ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        return err;
118ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    }
119ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    if (sigaction(SIGHUP, &act, &gOrigSigactionHUP) != 0) {
120ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        status_t err = -errno;
121eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        fprintf(stderr, "Unable to configure SIGHUP handler: %s\n",
122ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni                strerror(errno));
123ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        return err;
124ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    }
125ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    return NO_ERROR;
126ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni}
127ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
128eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni/*
129eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Returns "true" if the device is rotated 90 degrees.
1301ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni */
1311ffd86b448d78366190c540f98f8b6d641cdb6cfYang Nistatic bool isDeviceRotated(int orientation) {
132ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    return orientation != DISPLAY_ORIENTATION_0 &&
133eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            orientation != DISPLAY_ORIENTATION_180;
1341ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni}
1351ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
1361ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni/*
1371ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni * Configures and starts the MediaCodec encoder.  Obtains an input surface
138062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * from the codec.
139062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni */
140eb9aa675754c49f613c6ad71d41472b30f38b007Yang Nistatic status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec,
141eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        sp<IGraphicBufferProducer>* pBufferProducer) {
142062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    status_t err;
143062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
144eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (gVerbose) {
145eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        printf("Configuring recorder for %dx%d video at %.2fMbps\n",
146062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                gVideoWidth, gVideoHeight, gBitRate / 1000000.0);
147062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
148062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
149062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    sp<AMessage> format = new AMessage;
150eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    format->setInt32("width", gVideoWidth);
151062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    format->setInt32("height", gVideoHeight);
152062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    format->setString("mime", "video/avc");
153eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
154eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    format->setInt32("bitrate", gBitRate);
155eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    format->setFloat("frame-rate", displayFps);
1561ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    format->setInt32("i-frame-interval", 10);
157eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
158eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    sp<ALooper> looper = new ALooper;
159062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    looper->setName("screenrecord_looper");
160062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    looper->start();
161062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    ALOGV("Creating codec");
162eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    sp<MediaCodec> codec = MediaCodec::CreateByType(looper, "video/avc", true);
163da0f069871343119251d6b0586be356dc2146a62Yang Ni    if (codec == NULL) {
164eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        fprintf(stderr, "ERROR: unable to create video/avc codec instance\n");
165eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        return UNKNOWN_ERROR;
166da0f069871343119251d6b0586be356dc2146a62Yang Ni    }
167eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
168eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    err = codec->configure(format, NULL, NULL,
169da0f069871343119251d6b0586be356dc2146a62Yang Ni            MediaCodec::CONFIGURE_FLAG_ENCODE);
170da0f069871343119251d6b0586be356dc2146a62Yang Ni    if (err != NO_ERROR) {
171062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        fprintf(stderr, "ERROR: unable to configure codec (err=%d)\n", err);
172062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        codec->release();
173062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        return err;
174062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
175062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
176eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    ALOGV("Creating encoder input surface");
177062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    sp<IGraphicBufferProducer> bufferProducer;
178062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    err = codec->createInputSurface(&bufferProducer);
179062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (err != NO_ERROR) {
180062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        fprintf(stderr,
181062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            "ERROR: unable to create encoder input surface (err=%d)\n", err);
182062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        codec->release();
183062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        return err;
184062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
185062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
186062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    ALOGV("Starting codec");
1871ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    err = codec->start();
1881ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    if (err != NO_ERROR) {
1891ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        fprintf(stderr, "ERROR: unable to start codec (err=%d)\n", err);
190eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        codec->release();
191eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        return err;
192eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
193062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
194062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    ALOGV("Codec prepared");
195062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    *pCodec = codec;
196062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    *pBufferProducer = bufferProducer;
197062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    return 0;
198da0f069871343119251d6b0586be356dc2146a62Yang Ni}
199da0f069871343119251d6b0586be356dc2146a62Yang Ni
200da0f069871343119251d6b0586be356dc2146a62Yang Ni/*
201da0f069871343119251d6b0586be356dc2146a62Yang Ni * Sets the display projection, based on the display dimensions, video size,
202da0f069871343119251d6b0586be356dc2146a62Yang Ni * and device orientation.
203da0f069871343119251d6b0586be356dc2146a62Yang Ni */
204edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Nistatic status_t setDisplayProjection(const sp<IBinder>& dpy,
205edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        const DisplayInfo& mainDpyInfo) {
206edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    status_t err;
207edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
208edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // Set the region of the layer stack we're interested in, which in our
209edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // case is "all of it".  If the app is rotated (so that the width of the
210edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // app is based on the height of the display), reverse width/height.
211edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    bool deviceRotated = isDeviceRotated(mainDpyInfo.orientation);
212edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    uint32_t sourceWidth, sourceHeight;
213edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    if (!deviceRotated) {
214edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        sourceWidth = mainDpyInfo.w;
215edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        sourceHeight = mainDpyInfo.h;
216edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    } else {
217edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        ALOGV("using rotated width/height");
218edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        sourceHeight = mainDpyInfo.w;
219edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        sourceWidth = mainDpyInfo.h;
220edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    }
221edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    Rect layerStackRect(sourceWidth, sourceHeight);
222edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
223edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // We need to preserve the aspect ratio of the display.
224edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    float displayAspect = (float) sourceHeight / (float) sourceWidth;
225edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
226edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni
227edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // Set the way we map the output onto the display surface (which will
228edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // be e.g. 1280x720 for a 720p video).  The rect is interpreted
229edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    // post-rotation, so if the display is rotated 90 degrees we need to
230da0f069871343119251d6b0586be356dc2146a62Yang Ni    // "pre-rotate" it by flipping width/height, so that the orientation
231eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // adjustment changes it back.
232eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    //
233da0f069871343119251d6b0586be356dc2146a62Yang Ni    // We might want to encode a portrait display as landscape to use more
234da0f069871343119251d6b0586be356dc2146a62Yang Ni    // of the screen real estate.  (If players respect a 90-degree rotation
235da0f069871343119251d6b0586be356dc2146a62Yang Ni    // hint, we can essentially get a 720x1280 video instead of 1280x720.)
236062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    // In that case, we swap the configured video width/height and then
237062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    // supply a rotation value to the display projection.
238eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    uint32_t videoWidth, videoHeight;
239edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    uint32_t outWidth, outHeight;
240edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    if (!gRotate) {
241eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        videoWidth = gVideoWidth;
242eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        videoHeight = gVideoHeight;
243eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    } else {
244eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        videoWidth = gVideoHeight;
245eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        videoHeight = gVideoWidth;
246eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
247edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni    if (videoHeight > (uint32_t)(videoWidth * displayAspect)) {
248edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        // limited by narrow width; reduce height
249edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni        outWidth = videoWidth;
250eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        outHeight = (uint32_t)(videoWidth * displayAspect);
251eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    } else {
252eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        // limited by short height; restrict width
253062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        outHeight = videoHeight;
254062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        outWidth = (uint32_t)(videoHeight / displayAspect);
255062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
256062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    uint32_t offX, offY;
257062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    offX = (videoWidth - outWidth) / 2;
258062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    offY = (videoHeight - outHeight) / 2;
259062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    Rect displayRect(offX, offY, offX + outWidth, offY + outHeight);
260eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
261eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (gVerbose) {
262eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        if (gRotate) {
263eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            printf("Rotated content area is %ux%u at offset x=%d y=%d\n",
264eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    outHeight, outWidth, offY, offX);
265eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        } else {
266da0f069871343119251d6b0586be356dc2146a62Yang Ni            printf("Content area is %ux%u at offset x=%d y=%d\n",
267da0f069871343119251d6b0586be356dc2146a62Yang Ni                    outWidth, outHeight, offX, offY);
268da0f069871343119251d6b0586be356dc2146a62Yang Ni        }
269da0f069871343119251d6b0586be356dc2146a62Yang Ni    }
270eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
271da0f069871343119251d6b0586be356dc2146a62Yang Ni    SurfaceComposerClient::setDisplayProjection(dpy,
272eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            gRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0,
273eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            layerStackRect, displayRect);
274eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    return NO_ERROR;
275eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
276da0f069871343119251d6b0586be356dc2146a62Yang Ni
277eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni/*
278eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Configures the virtual display.  When this completes, virtual display
279eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * frames will start arriving from the buffer producer.
280eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni */
281da0f069871343119251d6b0586be356dc2146a62Yang Nistatic status_t prepareVirtualDisplay(const DisplayInfo& mainDpyInfo,
282eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        const sp<IGraphicBufferProducer>& bufferProducer,
283eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        sp<IBinder>* pDisplayHandle) {
284eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    sp<IBinder> dpy = SurfaceComposerClient::createDisplay(
285eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            String8("ScreenRecorder"), false /*secure*/);
286da0f069871343119251d6b0586be356dc2146a62Yang Ni
287eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    SurfaceComposerClient::openGlobalTransaction();
288eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    SurfaceComposerClient::setDisplaySurface(dpy, bufferProducer);
289eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    setDisplayProjection(dpy, mainDpyInfo);
290eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    SurfaceComposerClient::setDisplayLayerStack(dpy, 0);    // default stack
291eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    SurfaceComposerClient::closeGlobalTransaction();
292eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
293da0f069871343119251d6b0586be356dc2146a62Yang Ni    *pDisplayHandle = dpy;
294eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
295eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    return NO_ERROR;
296eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
297eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
298da0f069871343119251d6b0586be356dc2146a62Yang Ni/*
299eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Runs the MediaCodec encoder, sending the output to the MediaMuxer.  The
300da0f069871343119251d6b0586be356dc2146a62Yang Ni * input frames are coming from the virtual display as fast as SurfaceFlinger
301062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * wants to send them.
302062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni *
303062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * Exactly one of muxer or rawFp must be non-null.
304062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni *
305062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * The muxer must *not* have been started before calling.
306062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni */
307062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nistatic status_t runEncoder(const sp<MediaCodec>& encoder,
308062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        const sp<MediaMuxer>& muxer, FILE* rawFp, const sp<IBinder>& mainDpy,
309062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        const sp<IBinder>& virtualDpy, uint8_t orientation) {
310062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    static int kTimeout = 250000;   // be responsive on signal
311062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    status_t err;
312062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    ssize_t trackIdx = -1;
313062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    uint32_t debugNumFrames = 0;
314062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    int64_t startWhenNsec = systemTime(CLOCK_MONOTONIC);
315062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    int64_t endWhenNsec = startWhenNsec + seconds_to_nanoseconds(gTimeLimitSec);
316062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    DisplayInfo mainDpyInfo;
317062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
318062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL));
319062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
320062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    Vector<sp<ABuffer> > buffers;
321da0f069871343119251d6b0586be356dc2146a62Yang Ni    err = encoder->getOutputBuffers(&buffers);
322da0f069871343119251d6b0586be356dc2146a62Yang Ni    if (err != NO_ERROR) {
323da0f069871343119251d6b0586be356dc2146a62Yang Ni        fprintf(stderr, "Unable to get output buffers (err=%d)\n", err);
324062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        return err;
325da0f069871343119251d6b0586be356dc2146a62Yang Ni    }
326062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
327eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // This is set by the signal handler.
328eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    gStopRequested = false;
329da0f069871343119251d6b0586be356dc2146a62Yang Ni
330eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // Run until we're signaled.
331eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    while (!gStopRequested) {
332eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        size_t bufIndex, offset, size;
333da0f069871343119251d6b0586be356dc2146a62Yang Ni        int64_t ptsUsec;
334062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        uint32_t flags;
335062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
336062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) {
337da0f069871343119251d6b0586be356dc2146a62Yang Ni            if (gVerbose) {
338062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                printf("Time limit reached\n");
339eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
340eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            break;
341eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
342da0f069871343119251d6b0586be356dc2146a62Yang Ni
343eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        ALOGV("Calling dequeueOutputBuffer");
344eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        err = encoder->dequeueOutputBuffer(&bufIndex, &offset, &size, &ptsUsec,
345eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                &flags, kTimeout);
346062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        ALOGV("dequeueOutputBuffer returned %d", err);
347062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        switch (err) {
348062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        case NO_ERROR:
349062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            // got a buffer
350062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) != 0) {
351062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                ALOGV("Got codec config buffer (%u bytes)", size);
352062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                if (muxer != NULL) {
353062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    // ignore this -- we passed the CSD into MediaMuxer when
354062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    // we got the format change notification
355062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    size = 0;
356062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                }
357da0f069871343119251d6b0586be356dc2146a62Yang Ni            }
358062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            if (size != 0) {
359062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                ALOGV("Got data in buffer %d, size=%d, pts=%lld",
360062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                        bufIndex, size, ptsUsec);
361062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
362062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                { // scope
363062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    ATRACE_NAME("orientation");
364062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    // Check orientation, update if it has changed.
365062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    //
366062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    // Polling for changes is inefficient and wrong, but the
367062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    // useful stuff is hard to get at without a Dalvik VM.
368062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    err = SurfaceComposerClient::getDisplayInfo(mainDpy,
369062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                            &mainDpyInfo);
370062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    if (err != NO_ERROR) {
371eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                        ALOGW("getDisplayInfo(main) failed: %d", err);
372da0f069871343119251d6b0586be356dc2146a62Yang Ni                    } else if (orientation != mainDpyInfo.orientation) {
373433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                        ALOGD("orientation changed, now %d", mainDpyInfo.orientation);
374433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                        SurfaceComposerClient::openGlobalTransaction();
375433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                        setDisplayProjection(virtualDpy, mainDpyInfo);
376433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                        SurfaceComposerClient::closeGlobalTransaction();
377433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                        orientation = mainDpyInfo.orientation;
378433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                    }
379433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                }
380433558f0f9abbf07770db288183a15fd261cace2Yabin Cui
381433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                // If the virtual display isn't providing us with timestamps,
382433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                // use the current time.  This isn't great -- we could get
383433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                // decoded data in clusters -- but we're not expecting
384edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                // to hit this anyway.
385edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                if (ptsUsec == 0) {
386edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                    ptsUsec = systemTime(SYSTEM_TIME_MONOTONIC) / 1000;
387eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                }
388062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
389edf4ea312cc3f7dd4373f8db5aaf9325ff054c8eYang Ni                if (muxer == NULL) {
3902abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                    fwrite(buffers[bufIndex]->data(), 1, size, rawFp);
3912abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                    // Flush the data immediately in case we're streaming.
3922abfcc6d129fe3defddef4540aa95cc445c03a7aYang Ni                    // We don't want to do this if all we've written is
393eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    // the SPS/PPS data because mplayer gets confused.
394eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) == 0) {
395433558f0f9abbf07770db288183a15fd261cace2Yabin Cui                        fflush(rawFp);
396eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    }
397eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                } else {
398da0f069871343119251d6b0586be356dc2146a62Yang Ni                    // The MediaMuxer docs are unclear, but it appears that we
399eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    // need to pass either the full set of BufferInfo flags, or
400eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    // (flags & BUFFER_FLAG_SYNCFRAME).
401eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    //
402da0f069871343119251d6b0586be356dc2146a62Yang Ni                    // If this blocks for too long we could drop frames.  We may
403eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    // want to queue these up and do them on a different thread.
404da0f069871343119251d6b0586be356dc2146a62Yang Ni                    ATRACE_NAME("write sample");
405eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    assert(trackIdx != -1);
406eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    err = muxer->writeSampleData(buffers[bufIndex], trackIdx,
407eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                            ptsUsec, flags);
408eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    if (err != NO_ERROR) {
409da0f069871343119251d6b0586be356dc2146a62Yang Ni                        fprintf(stderr,
410062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                            "Failed writing data to muxer (err=%d)\n", err);
411062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                        return err;
412eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    }
413eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                }
414eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                debugNumFrames++;
415da0f069871343119251d6b0586be356dc2146a62Yang Ni            }
416eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            err = encoder->releaseOutputBuffer(bufIndex);
417062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            if (err != NO_ERROR) {
418062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                fprintf(stderr, "Unable to release output buffer (err=%d)\n",
419da0f069871343119251d6b0586be356dc2146a62Yang Ni                        err);
420da0f069871343119251d6b0586be356dc2146a62Yang Ni                return err;
4211ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni            }
4221ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni            if ((flags & MediaCodec::BUFFER_FLAG_EOS) != 0) {
4231ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni                // Not expecting EOS from SurfaceFlinger.  Go with it.
424eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                ALOGI("Received end-of-stream");
425eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                gStopRequested = true;
426eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            }
427eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            break;
4281ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni        case -EAGAIN:                       // INFO_TRY_AGAIN_LATER
4291ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni            ALOGV("Got -EAGAIN, looping");
430da0f069871343119251d6b0586be356dc2146a62Yang Ni            break;
431eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        case INFO_FORMAT_CHANGED:           // INFO_OUTPUT_FORMAT_CHANGED
432eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            {
433062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                // Format includes CSD, which we must provide to muxer.
434062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                ALOGV("Encoder format changed");
435eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                sp<AMessage> newFormat;
436eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                encoder->getOutputFormat(&newFormat);
437eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                if (muxer != NULL) {
438eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    trackIdx = muxer->addTrack(newFormat);
439eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    ALOGV("Starting muxer");
440eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    err = muxer->start();
441eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    if (err != NO_ERROR) {
442eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                        fprintf(stderr, "Unable to start muxer (err=%d)\n", err);
443eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                        return err;
444eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                    }
445ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni                }
446ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni            }
447ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni            break;
448062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        case INFO_OUTPUT_BUFFERS_CHANGED:   // INFO_OUTPUT_BUFFERS_CHANGED
449062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            // Not expected for an encoder; handle it anyway.
450062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            ALOGV("Encoder buffers changed");
451062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            err = encoder->getOutputBuffers(&buffers);
452062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            if (err != NO_ERROR) {
453062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                fprintf(stderr,
454062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                        "Unable to get new output buffers (err=%d)\n", err);
455062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                return err;
456062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            }
457062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            break;
458062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        case INVALID_OPERATION:
459062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            ALOGW("dequeueOutputBuffer returned INVALID_OPERATION");
460062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return err;
461062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        default:
462eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            fprintf(stderr,
463062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni                    "Got weird result %d from dequeueOutputBuffer\n", err);
464062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return err;
465062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
466062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    }
467062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
468062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    ALOGV("Encoder stopping (req=%d)", gStopRequested);
469eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (gVerbose) {
470eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        printf("Encoder stopping; recorded %u frames in %lld seconds\n",
4711ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni                debugNumFrames, nanoseconds_to_seconds(
4721ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni                        systemTime(CLOCK_MONOTONIC) - startWhenNsec));
4731ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    }
474da0f069871343119251d6b0586be356dc2146a62Yang Ni    return NO_ERROR;
475062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni}
476062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
477062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni/*
478062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * Raw H.264 byte stream output requested.  Send the output to stdout
479062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * if desired.  If the output is a tty, reconfigure it to avoid the
480062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni * CRLF line termination that we see with "adb shell" commands.
481062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni */
482062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nistatic FILE* prepareRawOutput(const char* fileName) {
483062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    FILE* rawFp = NULL;
484062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
485062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (strcmp(fileName, "-") == 0) {
486062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (gVerbose) {
487062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            fprintf(stderr, "ERROR: verbose output and '-' not compatible");
488062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return NULL;
489062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        }
490062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        rawFp = stdout;
491062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    } else {
492062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        rawFp = fopen(fileName, "w");
493062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni        if (rawFp == NULL) {
494062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            fprintf(stderr, "fopen raw failed: %s\n", strerror(errno));
495062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            return NULL;
496eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
497eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
498eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
499eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    int fd = fileno(rawFp);
500eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (isatty(fd)) {
501ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        // best effort -- reconfigure tty for "raw"
502ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        ALOGD("raw video output to tty (fd=%d)", fd);
503eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        struct termios term;
504eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        if (tcgetattr(fd, &term) == 0) {
505eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            cfmakeraw(&term);
506eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            if (tcsetattr(fd, TCSANOW, &term) == 0) {
507eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                ALOGD("tty successfully configured for raw");
508062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni            }
509eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        }
510eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
511ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni
512ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    return rawFp;
513eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni}
514eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
515eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni/*
516eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Main "do work" method.
517eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni *
518eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * Configures codec, muxer, and virtual display, then starts moving bits
519eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni * around.
520eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni */
521062c287f573ecc06c38ee4295e5627e12c52ac3dYang Nistatic status_t recordScreen(const char* fileName) {
522062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    status_t err;
523eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
524ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    // Configure signal handler.
525ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    err = configureSignals();
526062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    if (err != NO_ERROR) return err;
527eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni
528da0f069871343119251d6b0586be356dc2146a62Yang Ni    // Start Binder thread pool.  MediaCodec needs to be able to receive
529eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    // messages from mediaserver.
530eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    sp<ProcessState> self = ProcessState::self();
531eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    self->startThreadPool();
532da0f069871343119251d6b0586be356dc2146a62Yang Ni
533ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    // Get main display parameters.
534ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    sp<IBinder> mainDpy = SurfaceComposerClient::getBuiltInDisplay(
535eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni            ISurfaceComposer::eDisplayIdMain);
536eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    DisplayInfo mainDpyInfo;
537da0f069871343119251d6b0586be356dc2146a62Yang Ni    err = SurfaceComposerClient::getDisplayInfo(mainDpy, &mainDpyInfo);
538eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (err != NO_ERROR) {
539eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        fprintf(stderr, "ERROR: unable to get display characteristics\n");
540eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        return err;
541da0f069871343119251d6b0586be356dc2146a62Yang Ni    }
542eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (gVerbose) {
543eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        printf("Main display is %dx%d @%.2ffps (orientation=%u)\n",
544eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                mainDpyInfo.w, mainDpyInfo.h, mainDpyInfo.fps,
545eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni                mainDpyInfo.orientation);
546eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    }
547062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni
548062c287f573ecc06c38ee4295e5627e12c52ac3dYang Ni    bool rotated = isDeviceRotated(mainDpyInfo.orientation);
549eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (gVideoWidth == 0) {
550ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni        gVideoWidth = rotated ? mainDpyInfo.h : mainDpyInfo.w;
551ff2bb54ebf593b1d19d3a2e4cfa70a8ea4432c0dYang Ni    }
552eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni    if (gVideoHeight == 0) {
553eb9aa675754c49f613c6ad71d41472b30f38b007Yang Ni        gVideoHeight = rotated ? mainDpyInfo.w : mainDpyInfo.h;
5541ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    }
5551ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni
5561ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    // Configure and start the encoder.
5571ffd86b448d78366190c540f98f8b6d641cdb6cfYang Ni    sp<MediaCodec> encoder;
558    sp<IGraphicBufferProducer> encoderInputSurface;
559    err = prepareEncoder(mainDpyInfo.fps, &encoder, &encoderInputSurface);
560
561    if (err != NO_ERROR && !gSizeSpecified) {
562        // fallback is defined for landscape; swap if we're in portrait
563        bool needSwap = gVideoWidth < gVideoHeight;
564        uint32_t newWidth = needSwap ? kFallbackHeight : kFallbackWidth;
565        uint32_t newHeight = needSwap ? kFallbackWidth : kFallbackHeight;
566        if (gVideoWidth != newWidth && gVideoHeight != newHeight) {
567            ALOGV("Retrying with 720p");
568            fprintf(stderr, "WARNING: failed at %dx%d, retrying at %dx%d\n",
569                    gVideoWidth, gVideoHeight, newWidth, newHeight);
570            gVideoWidth = newWidth;
571            gVideoHeight = newHeight;
572            err = prepareEncoder(mainDpyInfo.fps, &encoder,
573                    &encoderInputSurface);
574        }
575    }
576    if (err != NO_ERROR) return err;
577
578    // From here on, we must explicitly release() the encoder before it goes
579    // out of scope, or we will get an assertion failure from stagefright
580    // later on in a different thread.
581
582
583    // Draw the "info" page by rendering a frame with GLES and sending
584    // it directly to the encoder.
585    // TODO: consider displaying this as a regular layer to avoid b/11697754
586    if (gWantInfoScreen) {
587        Overlay::drawInfoPage(encoderInputSurface);
588    }
589
590    // Configure optional overlay.
591    sp<IGraphicBufferProducer> bufferProducer;
592    sp<Overlay> overlay;
593    if (gWantFrameTime) {
594        // Send virtual display frames to an external texture.
595        overlay = new Overlay();
596        err = overlay->start(encoderInputSurface, &bufferProducer);
597        if (err != NO_ERROR) {
598            encoder->release();
599            return err;
600        }
601        if (gVerbose) {
602            printf("Bugreport overlay created\n");
603        }
604    } else {
605        // Use the encoder's input surface as the virtual display surface.
606        bufferProducer = encoderInputSurface;
607    }
608
609    // Configure virtual display.
610    sp<IBinder> dpy;
611    err = prepareVirtualDisplay(mainDpyInfo, bufferProducer, &dpy);
612    if (err != NO_ERROR) {
613        encoder->release();
614        return err;
615    }
616
617    sp<MediaMuxer> muxer = NULL;
618    FILE* rawFp = NULL;
619    if (gRawOutput) {
620        rawFp = prepareRawOutput(fileName);
621        if (rawFp == NULL) {
622            encoder->release();
623            return -1;
624        }
625    } else {
626        // Configure muxer.  We have to wait for the CSD blob from the encoder
627        // before we can start it.
628        muxer = new MediaMuxer(fileName, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
629        if (gRotate) {
630            muxer->setOrientationHint(90);  // TODO: does this do anything?
631        }
632    }
633
634    // Main encoder loop.
635    err = runEncoder(encoder, muxer, rawFp, mainDpy, dpy,
636            mainDpyInfo.orientation);
637    if (err != NO_ERROR) {
638        fprintf(stderr, "Encoder failed (err=%d)\n", err);
639        // fall through to cleanup
640    }
641
642    if (gVerbose) {
643        printf("Stopping encoder and muxer\n");
644    }
645
646    // Shut everything down, starting with the producer side.
647    encoderInputSurface = NULL;
648    SurfaceComposerClient::destroyDisplay(dpy);
649    if (overlay != NULL) {
650        overlay->stop();
651    }
652    encoder->stop();
653    if (muxer != NULL) {
654        // If we don't stop muxer explicitly, i.e. let the destructor run,
655        // it may hang (b/11050628).
656        muxer->stop();
657    } else if (rawFp != stdout) {
658        fclose(rawFp);
659    }
660    encoder->release();
661
662    return err;
663}
664
665/*
666 * Sends a broadcast to the media scanner to tell it about the new video.
667 *
668 * This is optional, but nice to have.
669 */
670static status_t notifyMediaScanner(const char* fileName) {
671    // need to do allocations before the fork()
672    String8 fileUrl("file://");
673    fileUrl.append(fileName);
674
675    const char* kCommand = "/system/bin/am";
676    const char* const argv[] = {
677            kCommand,
678            "broadcast",
679            "-a",
680            "android.intent.action.MEDIA_SCANNER_SCAN_FILE",
681            "-d",
682            fileUrl.string(),
683            NULL
684    };
685    if (gVerbose) {
686        printf("Executing:");
687        for (int i = 0; argv[i] != NULL; i++) {
688            printf(" %s", argv[i]);
689        }
690        putchar('\n');
691    }
692
693    pid_t pid = fork();
694    if (pid < 0) {
695        int err = errno;
696        ALOGW("fork() failed: %s", strerror(err));
697        return -err;
698    } else if (pid > 0) {
699        // parent; wait for the child, mostly to make the verbose-mode output
700        // look right, but also to check for and log failures
701        int status;
702        pid_t actualPid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
703        if (actualPid != pid) {
704            ALOGW("waitpid(%d) returned %d (errno=%d)", pid, actualPid, errno);
705        } else if (status != 0) {
706            ALOGW("'am broadcast' exited with status=%d", status);
707        } else {
708            ALOGV("'am broadcast' exited successfully");
709        }
710    } else {
711        if (!gVerbose) {
712            // non-verbose, suppress 'am' output
713            ALOGV("closing stdout/stderr in child");
714            int fd = open("/dev/null", O_WRONLY);
715            if (fd >= 0) {
716                dup2(fd, STDOUT_FILENO);
717                dup2(fd, STDERR_FILENO);
718                close(fd);
719            }
720        }
721        execv(kCommand, const_cast<char* const*>(argv));
722        ALOGE("execv(%s) failed: %s\n", kCommand, strerror(errno));
723        exit(1);
724    }
725    return NO_ERROR;
726}
727
728/*
729 * Parses a string of the form "1280x720".
730 *
731 * Returns true on success.
732 */
733static bool parseWidthHeight(const char* widthHeight, uint32_t* pWidth,
734        uint32_t* pHeight) {
735    long width, height;
736    char* end;
737
738    // Must specify base 10, or "0x0" gets parsed differently.
739    width = strtol(widthHeight, &end, 10);
740    if (end == widthHeight || *end != 'x' || *(end+1) == '\0') {
741        // invalid chars in width, or missing 'x', or missing height
742        return false;
743    }
744    height = strtol(end + 1, &end, 10);
745    if (*end != '\0') {
746        // invalid chars in height
747        return false;
748    }
749
750    *pWidth = width;
751    *pHeight = height;
752    return true;
753}
754
755/*
756 * Accepts a string with a bare number ("4000000") or with a single-character
757 * unit ("4m").
758 *
759 * Returns an error if parsing fails.
760 */
761static status_t parseValueWithUnit(const char* str, uint32_t* pValue) {
762    long value;
763    char* endptr;
764
765    value = strtol(str, &endptr, 10);
766    if (*endptr == '\0') {
767        // bare number
768        *pValue = value;
769        return NO_ERROR;
770    } else if (toupper(*endptr) == 'M' && *(endptr+1) == '\0') {
771        *pValue = value * 1000000;  // check for overflow?
772        return NO_ERROR;
773    } else {
774        fprintf(stderr, "Unrecognized value: %s\n", str);
775        return UNKNOWN_ERROR;
776    }
777}
778
779/*
780 * Dumps usage on stderr.
781 */
782static void usage() {
783    fprintf(stderr,
784        "Usage: screenrecord [options] <filename>\n"
785        "\n"
786        "Android screenrecord v%d.%d.  Records the device's display to a .mp4 file.\n"
787        "\n"
788        "Options:\n"
789        "--size WIDTHxHEIGHT\n"
790        "    Set the video size, e.g. \"1280x720\".  Default is the device's main\n"
791        "    display resolution (if supported), 1280x720 if not.  For best results,\n"
792        "    use a size supported by the AVC encoder.\n"
793        "--bit-rate RATE\n"
794        "    Set the video bit rate, in bits per second.  Value may be specified as\n"
795        "    bits or megabits, e.g. '4000000' is equivalent to '4M'.  Default %dMbps.\n"
796        "--bugreport\n"
797        "    Add additional information, such as a timestamp overlay, that is helpful\n"
798        "    in videos captured to illustrate bugs.\n"
799        "--time-limit TIME\n"
800        "    Set the maximum recording time, in seconds.  Default / maximum is %d.\n"
801        "--verbose\n"
802        "    Display interesting information on stdout.\n"
803        "--help\n"
804        "    Show this message.\n"
805        "\n"
806        "Recording continues until Ctrl-C is hit or the time limit is reached.\n"
807        "\n",
808        kVersionMajor, kVersionMinor, gBitRate / 1000000, gTimeLimitSec
809        );
810}
811
812/*
813 * Parses args and kicks things off.
814 */
815int main(int argc, char* const argv[]) {
816    static const struct option longOptions[] = {
817        { "help",               no_argument,        NULL, 'h' },
818        { "verbose",            no_argument,        NULL, 'v' },
819        { "size",               required_argument,  NULL, 's' },
820        { "bit-rate",           required_argument,  NULL, 'b' },
821        { "time-limit",         required_argument,  NULL, 't' },
822        { "show-device-info",   no_argument,        NULL, 'i' },
823        { "show-frame-time",    no_argument,        NULL, 'f' },
824        { "bugreport",          no_argument,        NULL, 'u' },
825        { "rotate",             no_argument,        NULL, 'r' },
826        { "raw",                no_argument,        NULL, 'w' },
827        { NULL,                 0,                  NULL, 0 }
828    };
829
830    while (true) {
831        int optionIndex = 0;
832        int ic = getopt_long(argc, argv, "", longOptions, &optionIndex);
833        if (ic == -1) {
834            break;
835        }
836
837        switch (ic) {
838        case 'h':
839            usage();
840            return 0;
841        case 'v':
842            gVerbose = true;
843            break;
844        case 's':
845            if (!parseWidthHeight(optarg, &gVideoWidth, &gVideoHeight)) {
846                fprintf(stderr, "Invalid size '%s', must be width x height\n",
847                        optarg);
848                return 2;
849            }
850            if (gVideoWidth == 0 || gVideoHeight == 0) {
851                fprintf(stderr,
852                    "Invalid size %ux%u, width and height may not be zero\n",
853                    gVideoWidth, gVideoHeight);
854                return 2;
855            }
856            gSizeSpecified = true;
857            break;
858        case 'b':
859            if (parseValueWithUnit(optarg, &gBitRate) != NO_ERROR) {
860                return 2;
861            }
862            if (gBitRate < kMinBitRate || gBitRate > kMaxBitRate) {
863                fprintf(stderr,
864                        "Bit rate %dbps outside acceptable range [%d,%d]\n",
865                        gBitRate, kMinBitRate, kMaxBitRate);
866                return 2;
867            }
868            break;
869        case 't':
870            gTimeLimitSec = atoi(optarg);
871            if (gTimeLimitSec == 0 || gTimeLimitSec > kMaxTimeLimitSec) {
872                fprintf(stderr,
873                        "Time limit %ds outside acceptable range [1,%d]\n",
874                        gTimeLimitSec, kMaxTimeLimitSec);
875                return 2;
876            }
877            break;
878        case 'i':
879            gWantInfoScreen = true;
880            break;
881        case 'f':
882            gWantFrameTime = true;
883            break;
884        case 'u':
885            gWantInfoScreen = true;
886            gWantFrameTime = true;
887            break;
888        case 'r':
889            // experimental feature
890            gRotate = true;
891            break;
892        case 'w':
893            // experimental feature
894            gRawOutput = true;
895            break;
896        default:
897            if (ic != '?') {
898                fprintf(stderr, "getopt_long returned unexpected value 0x%x\n", ic);
899            }
900            return 2;
901        }
902    }
903
904    if (optind != argc - 1) {
905        fprintf(stderr, "Must specify output file (see --help).\n");
906        return 2;
907    }
908
909    const char* fileName = argv[optind];
910    if (!gRawOutput) {
911        // MediaMuxer tries to create the file in the constructor, but we don't
912        // learn about the failure until muxer.start(), which returns a generic
913        // error code without logging anything.  We attempt to create the file
914        // now for better diagnostics.
915        int fd = open(fileName, O_CREAT | O_RDWR, 0644);
916        if (fd < 0) {
917            fprintf(stderr, "Unable to open '%s': %s\n", fileName, strerror(errno));
918            return 1;
919        }
920        close(fd);
921    }
922
923    status_t err = recordScreen(fileName);
924    if (err == NO_ERROR) {
925        // Try to notify the media scanner.  Not fatal if this fails.
926        notifyMediaScanner(fileName);
927    }
928    ALOGD(err == NO_ERROR ? "success" : "failed");
929    return (int) err;
930}
931