screenrecord.cpp revision 2d11a2031b99db9b503a7ad7efd1f18606af4012
113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi/* 213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * Copyright 2013 The Android Open Source Project 313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * 413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * you may not use this file except in compliance with the License. 613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * You may obtain a copy of the License at 713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * 813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * 1013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 1113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 1213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * See the License for the specific language governing permissions and 1413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * limitations under the License. 1513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi */ 1613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 17e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi#define LOG_TAG "ScreenRecord" 1813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#define ATRACE_TAG ATRACE_TAG_GRAPHICS 1913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi//#define LOG_NDEBUG 0 202b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi#include <utils/Log.h> 2113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 224ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi#include <binder/IPCThreadState.h> 234ee246c55533bdab8ab5fa0f0581744fe58e7c91Jean-Michel Trivi#include <utils/Errors.h> 2413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <utils/Timers.h> 2513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <utils/Trace.h> 2613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 2713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <gui/Surface.h> 2813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <gui/SurfaceComposerClient.h> 2913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <gui/ISurfaceComposer.h> 3013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <ui/DisplayInfo.h> 31e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi#include <media/openmax/OMX_IVCommon.h> 3213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <media/stagefright/foundation/ABuffer.h> 3313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <media/stagefright/foundation/AMessage.h> 3413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <media/stagefright/MediaCodec.h> 3513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <media/stagefright/MediaErrors.h> 3613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <media/stagefright/MediaMuxer.h> 37e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi#include <media/ICrypto.h> 3813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 3913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <stdlib.h> 4013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <unistd.h> 4113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <string.h> 4213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <stdio.h> 4313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <ctype.h> 4413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <fcntl.h> 4513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <signal.h> 4613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <getopt.h> 4713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <sys/wait.h> 4813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include <termios.h> 49e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi#include <assert.h> 5013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 51e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi#include "screenrecord.h" 5213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi#include "Overlay.h" 5313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 5413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Triviusing namespace android; 5513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 5613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic const uint32_t kMinBitRate = 100000; // 0.1Mbps 5713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic const uint32_t kMaxBitRate = 200 * 1000000; // 200Mbps 5813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic const uint32_t kMaxTimeLimitSec = 180; // 3 minutes 5913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic const uint32_t kFallbackWidth = 1280; // 720p 6013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic const uint32_t kFallbackHeight = 720; 6113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 6213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi// Command-line parameters. 6313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic bool gVerbose = false; // chatty on stdout 6413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic bool gRotate = false; // rotate 90 degrees 6513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic bool gRawOutput = false; // generate raw H.264 byte stream output 6613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic bool gSizeSpecified = false; // was size explicitly requested? 6713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic bool gWantInfoScreen = false; // do we want initial info screen? 6813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic bool gWantFrameTime = false; // do we want times on each frame? 6913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic uint32_t gVideoWidth = 0; // default width+height 7013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic uint32_t gVideoHeight = 0; 7113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic uint32_t gBitRate = 4000000; // 4Mbps 7213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic uint32_t gTimeLimitSec = kMaxTimeLimitSec; 7313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 7413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi// Set by signal handler to stop recording. 7513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic volatile bool gStopRequested; 7613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 7713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi// Previous signal handler state, restored after first hit. 78a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kastenstatic struct sigaction gOrigSigactionINT; 7913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic struct sigaction gOrigSigactionHUP; 8013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 8113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 8213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi/* 8313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * Catch keyboard interrupt signals. On receipt, the "stop requested" 8413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * flag is raised, and the original handler is restored (so that, if 8513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * we get stuck finishing, a second Ctrl-C will kill the process). 8613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi */ 8713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic void signalCatcher(int signum) 8813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi{ 8913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi gStopRequested = true; 9013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi switch (signum) { 9113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi case SIGINT: 9213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi case SIGHUP: 9313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi sigaction(SIGINT, &gOrigSigactionINT, NULL); 9413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi sigaction(SIGHUP, &gOrigSigactionHUP, NULL); 9513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi break; 96e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi default: 9713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi abort(); 9813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi break; 9913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi } 10013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi} 10113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi 102e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi/* 10313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * Configures signal handlers. The previous handlers are saved. 10413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * 10513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * If the command is run from an interactive adb shell, we get SIGINT 10613837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * when Ctrl-C is hit. If we're run from the host, the local adb process 10713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi * gets the signal, and we get a SIGHUP when the terminal disconnects. 10813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi */ 10913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivistatic status_t configureSignals() { 11013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi struct sigaction act; 11113837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi memset(&act, 0, sizeof(act)); 11213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi act.sa_handler = signalCatcher; 11313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi if (sigaction(SIGINT, &act, &gOrigSigactionINT) != 0) { 11413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi status_t err = -errno; 11513837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi fprintf(stderr, "Unable to configure SIGINT handler: %s\n", 116e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi strerror(errno)); 11713837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi return err; 11813837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi } 11913837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi if (sigaction(SIGHUP, &act, &gOrigSigactionHUP) != 0) { 12013837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi status_t err = -errno; 121e9236d046fdb5cac0696c42e03443a2439188146Jean-Michel Trivi fprintf(stderr, "Unable to configure SIGHUP handler: %s\n", 12213837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi strerror(errno)); 12313837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi return err; 12413837cf3f7be0eb8b1a9552bd99a89f98c987720Jean-Michel Trivi } 125 return NO_ERROR; 126} 127 128/* 129 * Returns "true" if the device is rotated 90 degrees. 130 */ 131static bool isDeviceRotated(int orientation) { 132 return orientation != DISPLAY_ORIENTATION_0 && 133 orientation != DISPLAY_ORIENTATION_180; 134} 135 136/* 137 * Configures and starts the MediaCodec encoder. Obtains an input surface 138 * from the codec. 139 */ 140static status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec, 141 sp<IGraphicBufferProducer>* pBufferProducer) { 142 status_t err; 143 144 if (gVerbose) { 145 printf("Configuring recorder for %dx%d video at %.2fMbps\n", 146 gVideoWidth, gVideoHeight, gBitRate / 1000000.0); 147 } 148 149 sp<AMessage> format = new AMessage; 150 format->setInt32("width", gVideoWidth); 151 format->setInt32("height", gVideoHeight); 152 format->setString("mime", "video/avc"); 153 format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque); 154 format->setInt32("bitrate", gBitRate); 155 format->setFloat("frame-rate", displayFps); 156 format->setInt32("i-frame-interval", 10); 157 158 sp<ALooper> looper = new ALooper; 159 looper->setName("screenrecord_looper"); 160 looper->start(); 161 ALOGV("Creating codec"); 162 sp<MediaCodec> codec = MediaCodec::CreateByType(looper, "video/avc", true); 163 if (codec == NULL) { 164 fprintf(stderr, "ERROR: unable to create video/avc codec instance\n"); 165 return UNKNOWN_ERROR; 166 } 167 168 err = codec->configure(format, NULL, NULL, 169 MediaCodec::CONFIGURE_FLAG_ENCODE); 170 if (err != NO_ERROR) { 171 fprintf(stderr, "ERROR: unable to configure codec (err=%d)\n", err); 172 codec->release(); 173 return err; 174 } 175 176 ALOGV("Creating encoder input surface"); 177 sp<IGraphicBufferProducer> bufferProducer; 178 err = codec->createInputSurface(&bufferProducer); 179 if (err != NO_ERROR) { 180 fprintf(stderr, 181 "ERROR: unable to create encoder input surface (err=%d)\n", err); 182 codec->release(); 183 return err; 184 } 185 186 ALOGV("Starting codec"); 187 err = codec->start(); 188 if (err != NO_ERROR) { 189 fprintf(stderr, "ERROR: unable to start codec (err=%d)\n", err); 190 codec->release(); 191 return err; 192 } 193 194 ALOGV("Codec prepared"); 195 *pCodec = codec; 196 *pBufferProducer = bufferProducer; 197 return 0; 198} 199 200/* 201 * Sets the display projection, based on the display dimensions, video size, 202 * and device orientation. 203 */ 204static status_t setDisplayProjection(const sp<IBinder>& dpy, 205 const DisplayInfo& mainDpyInfo) { 206 status_t err; 207 208 // Set the region of the layer stack we're interested in, which in our 209 // case is "all of it". If the app is rotated (so that the width of the 210 // app is based on the height of the display), reverse width/height. 211 bool deviceRotated = isDeviceRotated(mainDpyInfo.orientation); 212 uint32_t sourceWidth, sourceHeight; 213 if (!deviceRotated) { 214 sourceWidth = mainDpyInfo.w; 215 sourceHeight = mainDpyInfo.h; 216 } else { 217 ALOGV("using rotated width/height"); 218 sourceHeight = mainDpyInfo.w; 219 sourceWidth = mainDpyInfo.h; 220 } 221 Rect layerStackRect(sourceWidth, sourceHeight); 222 223 // We need to preserve the aspect ratio of the display. 224 float displayAspect = (float) sourceHeight / (float) sourceWidth; 225 226 227 // Set the way we map the output onto the display surface (which will 228 // be e.g. 1280x720 for a 720p video). The rect is interpreted 229 // post-rotation, so if the display is rotated 90 degrees we need to 230 // "pre-rotate" it by flipping width/height, so that the orientation 231 // adjustment changes it back. 232 // 233 // We might want to encode a portrait display as landscape to use more 234 // of the screen real estate. (If players respect a 90-degree rotation 235 // hint, we can essentially get a 720x1280 video instead of 1280x720.) 236 // In that case, we swap the configured video width/height and then 237 // supply a rotation value to the display projection. 238 uint32_t videoWidth, videoHeight; 239 uint32_t outWidth, outHeight; 240 if (!gRotate) { 241 videoWidth = gVideoWidth; 242 videoHeight = gVideoHeight; 243 } else { 244 videoWidth = gVideoHeight; 245 videoHeight = gVideoWidth; 246 } 247 if (videoHeight > (uint32_t)(videoWidth * displayAspect)) { 248 // limited by narrow width; reduce height 249 outWidth = videoWidth; 250 outHeight = (uint32_t)(videoWidth * displayAspect); 251 } else { 252 // limited by short height; restrict width 253 outHeight = videoHeight; 254 outWidth = (uint32_t)(videoHeight / displayAspect); 255 } 256 uint32_t offX, offY; 257 offX = (videoWidth - outWidth) / 2; 258 offY = (videoHeight - outHeight) / 2; 259 Rect displayRect(offX, offY, offX + outWidth, offY + outHeight); 260 261 if (gVerbose) { 262 if (gRotate) { 263 printf("Rotated content area is %ux%u at offset x=%d y=%d\n", 264 outHeight, outWidth, offY, offX); 265 } else { 266 printf("Content area is %ux%u at offset x=%d y=%d\n", 267 outWidth, outHeight, offX, offY); 268 } 269 } 270 271 SurfaceComposerClient::setDisplayProjection(dpy, 272 gRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0, 273 layerStackRect, displayRect); 274 return NO_ERROR; 275} 276 277/* 278 * Configures the virtual display. When this completes, virtual display 279 * frames will start arriving from the buffer producer. 280 */ 281static status_t prepareVirtualDisplay(const DisplayInfo& mainDpyInfo, 282 const sp<IGraphicBufferProducer>& bufferProducer, 283 sp<IBinder>* pDisplayHandle) { 284 sp<IBinder> dpy = SurfaceComposerClient::createDisplay( 285 String8("ScreenRecorder"), false /*secure*/); 286 287 SurfaceComposerClient::openGlobalTransaction(); 288 SurfaceComposerClient::setDisplaySurface(dpy, bufferProducer); 289 setDisplayProjection(dpy, mainDpyInfo); 290 SurfaceComposerClient::setDisplayLayerStack(dpy, 0); // default stack 291 SurfaceComposerClient::closeGlobalTransaction(); 292 293 *pDisplayHandle = dpy; 294 295 return NO_ERROR; 296} 297 298/* 299 * Runs the MediaCodec encoder, sending the output to the MediaMuxer. The 300 * input frames are coming from the virtual display as fast as SurfaceFlinger 301 * wants to send them. 302 * 303 * Exactly one of muxer or rawFp must be non-null. 304 * 305 * The muxer must *not* have been started before calling. 306 */ 307static status_t runEncoder(const sp<MediaCodec>& encoder, 308 const sp<MediaMuxer>& muxer, FILE* rawFp, const sp<IBinder>& mainDpy, 309 const sp<IBinder>& virtualDpy, uint8_t orientation) { 310 static int kTimeout = 250000; // be responsive on signal 311 status_t err; 312 ssize_t trackIdx = -1; 313 uint32_t debugNumFrames = 0; 314 int64_t startWhenNsec = systemTime(CLOCK_MONOTONIC); 315 int64_t endWhenNsec = startWhenNsec + seconds_to_nanoseconds(gTimeLimitSec); 316 DisplayInfo mainDpyInfo; 317 318 assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL)); 319 320 Vector<sp<ABuffer> > buffers; 321 err = encoder->getOutputBuffers(&buffers); 322 if (err != NO_ERROR) { 323 fprintf(stderr, "Unable to get output buffers (err=%d)\n", err); 324 return err; 325 } 326 327 // This is set by the signal handler. 328 gStopRequested = false; 329 330 // Run until we're signaled. 331 while (!gStopRequested) { 332 size_t bufIndex, offset, size; 333 int64_t ptsUsec; 334 uint32_t flags; 335 336 if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) { 337 if (gVerbose) { 338 printf("Time limit reached\n"); 339 } 340 break; 341 } 342 343 ALOGV("Calling dequeueOutputBuffer"); 344 err = encoder->dequeueOutputBuffer(&bufIndex, &offset, &size, &ptsUsec, 345 &flags, kTimeout); 346 ALOGV("dequeueOutputBuffer returned %d", err); 347 switch (err) { 348 case NO_ERROR: 349 // got a buffer 350 if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) != 0) { 351 ALOGV("Got codec config buffer (%u bytes)", size); 352 if (muxer != NULL) { 353 // ignore this -- we passed the CSD into MediaMuxer when 354 // we got the format change notification 355 size = 0; 356 } 357 } 358 if (size != 0) { 359 ALOGV("Got data in buffer %d, size=%d, pts=%lld", 360 bufIndex, size, ptsUsec); 361 362 { // scope 363 ATRACE_NAME("orientation"); 364 // Check orientation, update if it has changed. 365 // 366 // Polling for changes is inefficient and wrong, but the 367 // useful stuff is hard to get at without a Dalvik VM. 368 err = SurfaceComposerClient::getDisplayInfo(mainDpy, 369 &mainDpyInfo); 370 if (err != NO_ERROR) { 371 ALOGW("getDisplayInfo(main) failed: %d", err); 372 } else if (orientation != mainDpyInfo.orientation) { 373 ALOGD("orientation changed, now %d", mainDpyInfo.orientation); 374 SurfaceComposerClient::openGlobalTransaction(); 375 setDisplayProjection(virtualDpy, mainDpyInfo); 376 SurfaceComposerClient::closeGlobalTransaction(); 377 orientation = mainDpyInfo.orientation; 378 } 379 } 380 381 // If the virtual display isn't providing us with timestamps, 382 // use the current time. This isn't great -- we could get 383 // decoded data in clusters -- but we're not expecting 384 // to hit this anyway. 385 if (ptsUsec == 0) { 386 ptsUsec = systemTime(SYSTEM_TIME_MONOTONIC) / 1000; 387 } 388 389 if (muxer == NULL) { 390 fwrite(buffers[bufIndex]->data(), 1, size, rawFp); 391 // Flush the data immediately in case we're streaming. 392 // We don't want to do this if all we've written is 393 // the SPS/PPS data because mplayer gets confused. 394 if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) == 0) { 395 fflush(rawFp); 396 } 397 } else { 398 // The MediaMuxer docs are unclear, but it appears that we 399 // need to pass either the full set of BufferInfo flags, or 400 // (flags & BUFFER_FLAG_SYNCFRAME). 401 // 402 // If this blocks for too long we could drop frames. We may 403 // want to queue these up and do them on a different thread. 404 ATRACE_NAME("write sample"); 405 assert(trackIdx != -1); 406 err = muxer->writeSampleData(buffers[bufIndex], trackIdx, 407 ptsUsec, flags); 408 if (err != NO_ERROR) { 409 fprintf(stderr, 410 "Failed writing data to muxer (err=%d)\n", err); 411 return err; 412 } 413 } 414 debugNumFrames++; 415 } 416 err = encoder->releaseOutputBuffer(bufIndex); 417 if (err != NO_ERROR) { 418 fprintf(stderr, "Unable to release output buffer (err=%d)\n", 419 err); 420 return err; 421 } 422 if ((flags & MediaCodec::BUFFER_FLAG_EOS) != 0) { 423 // Not expecting EOS from SurfaceFlinger. Go with it. 424 ALOGI("Received end-of-stream"); 425 gStopRequested = true; 426 } 427 break; 428 case -EAGAIN: // INFO_TRY_AGAIN_LATER 429 ALOGV("Got -EAGAIN, looping"); 430 break; 431 case INFO_FORMAT_CHANGED: // INFO_OUTPUT_FORMAT_CHANGED 432 { 433 // Format includes CSD, which we must provide to muxer. 434 ALOGV("Encoder format changed"); 435 sp<AMessage> newFormat; 436 encoder->getOutputFormat(&newFormat); 437 if (muxer != NULL) { 438 trackIdx = muxer->addTrack(newFormat); 439 ALOGV("Starting muxer"); 440 err = muxer->start(); 441 if (err != NO_ERROR) { 442 fprintf(stderr, "Unable to start muxer (err=%d)\n", err); 443 return err; 444 } 445 } 446 } 447 break; 448 case INFO_OUTPUT_BUFFERS_CHANGED: // INFO_OUTPUT_BUFFERS_CHANGED 449 // Not expected for an encoder; handle it anyway. 450 ALOGV("Encoder buffers changed"); 451 err = encoder->getOutputBuffers(&buffers); 452 if (err != NO_ERROR) { 453 fprintf(stderr, 454 "Unable to get new output buffers (err=%d)\n", err); 455 return err; 456 } 457 break; 458 case INVALID_OPERATION: 459 ALOGW("dequeueOutputBuffer returned INVALID_OPERATION"); 460 return err; 461 default: 462 fprintf(stderr, 463 "Got weird result %d from dequeueOutputBuffer\n", err); 464 return err; 465 } 466 } 467 468 ALOGV("Encoder stopping (req=%d)", gStopRequested); 469 if (gVerbose) { 470 printf("Encoder stopping; recorded %u frames in %lld seconds\n", 471 debugNumFrames, nanoseconds_to_seconds( 472 systemTime(CLOCK_MONOTONIC) - startWhenNsec)); 473 } 474 return NO_ERROR; 475} 476 477/* 478 * Raw H.264 byte stream output requested. Send the output to stdout 479 * if desired. If the output is a tty, reconfigure it to avoid the 480 * CRLF line termination that we see with "adb shell" commands. 481 */ 482static FILE* prepareRawOutput(const char* fileName) { 483 FILE* rawFp = NULL; 484 485 if (strcmp(fileName, "-") == 0) { 486 if (gVerbose) { 487 fprintf(stderr, "ERROR: verbose output and '-' not compatible"); 488 return NULL; 489 } 490 rawFp = stdout; 491 } else { 492 rawFp = fopen(fileName, "w"); 493 if (rawFp == NULL) { 494 fprintf(stderr, "fopen raw failed: %s\n", strerror(errno)); 495 return NULL; 496 } 497 } 498 499 int fd = fileno(rawFp); 500 if (isatty(fd)) { 501 // best effort -- reconfigure tty for "raw" 502 ALOGD("raw video output to tty (fd=%d)", fd); 503 struct termios term; 504 if (tcgetattr(fd, &term) == 0) { 505 cfmakeraw(&term); 506 if (tcsetattr(fd, TCSANOW, &term) == 0) { 507 ALOGD("tty successfully configured for raw"); 508 } 509 } 510 } 511 512 return rawFp; 513} 514 515/* 516 * Main "do work" method. 517 * 518 * Configures codec, muxer, and virtual display, then starts moving bits 519 * around. 520 */ 521static status_t recordScreen(const char* fileName) { 522 status_t err; 523 524 // Configure signal handler. 525 err = configureSignals(); 526 if (err != NO_ERROR) return err; 527 528 // Start Binder thread pool. MediaCodec needs to be able to receive 529 // messages from mediaserver. 530 sp<ProcessState> self = ProcessState::self(); 531 self->startThreadPool(); 532 533 // Get main display parameters. 534 sp<IBinder> mainDpy = SurfaceComposerClient::getBuiltInDisplay( 535 ISurfaceComposer::eDisplayIdMain); 536 DisplayInfo mainDpyInfo; 537 err = SurfaceComposerClient::getDisplayInfo(mainDpy, &mainDpyInfo); 538 if (err != NO_ERROR) { 539 fprintf(stderr, "ERROR: unable to get display characteristics\n"); 540 return err; 541 } 542 if (gVerbose) { 543 printf("Main display is %dx%d @%.2ffps (orientation=%u)\n", 544 mainDpyInfo.w, mainDpyInfo.h, mainDpyInfo.fps, 545 mainDpyInfo.orientation); 546 } 547 548 bool rotated = isDeviceRotated(mainDpyInfo.orientation); 549 if (gVideoWidth == 0) { 550 gVideoWidth = rotated ? mainDpyInfo.h : mainDpyInfo.w; 551 } 552 if (gVideoHeight == 0) { 553 gVideoHeight = rotated ? mainDpyInfo.w : mainDpyInfo.h; 554 } 555 556 // Configure and start the encoder. 557 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