1 /*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <assert.h>
18 #include <ctype.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <getopt.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sys/wait.h>
29
30 #include <termios.h>
31 #include <unistd.h>
32
33 #define LOG_TAG "ScreenRecord"
34 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
35 //#define LOG_NDEBUG 0
36 #include <utils/Log.h>
37
38 #include <binder/IPCThreadState.h>
39 #include <utils/Errors.h>
40 #include <utils/Timers.h>
41 #include <utils/Trace.h>
42
43 #include <gui/Surface.h>
44 #include <gui/SurfaceComposerClient.h>
45 #include <gui/ISurfaceComposer.h>
46 #include <ui/DisplayInfo.h>
47 #include <media/openmax/OMX_IVCommon.h>
48 #include <media/stagefright/foundation/ABuffer.h>
49 #include <media/stagefright/foundation/AMessage.h>
50 #include <media/stagefright/MediaCodec.h>
51 #include <media/stagefright/MediaErrors.h>
52 #include <media/stagefright/MediaMuxer.h>
53 #include <media/stagefright/PersistentSurface.h>
54 #include <media/ICrypto.h>
55 #include <media/MediaCodecBuffer.h>
56
57 #include "screenrecord.h"
58 #include "Overlay.h"
59 #include "FrameOutput.h"
60
61 using namespace android;
62
63 static const uint32_t kMinBitRate = 100000; // 0.1Mbps
64 static const uint32_t kMaxBitRate = 200 * 1000000; // 200Mbps
65 static const uint32_t kMaxTimeLimitSec = 180; // 3 minutes
66 static const uint32_t kFallbackWidth = 1280; // 720p
67 static const uint32_t kFallbackHeight = 720;
68 static const char* kMimeTypeAvc = "video/avc";
69
70 // Command-line parameters.
71 static bool gVerbose = false; // chatty on stdout
72 static bool gRotate = false; // rotate 90 degrees
73 static bool gMonotonicTime = false; // use system monotonic time for timestamps
74 static bool gPersistentSurface = false; // use persistent surface
75 static enum {
76 FORMAT_MP4, FORMAT_H264, FORMAT_FRAMES, FORMAT_RAW_FRAMES
77 } gOutputFormat = FORMAT_MP4; // data format for output
78 static AString gCodecName = ""; // codec name override
79 static bool gSizeSpecified = false; // was size explicitly requested?
80 static bool gWantInfoScreen = false; // do we want initial info screen?
81 static bool gWantFrameTime = false; // do we want times on each frame?
82 static uint32_t gVideoWidth = 0; // default width+height
83 static uint32_t gVideoHeight = 0;
84 static uint32_t gBitRate = 20000000; // 20Mbps
85 static uint32_t gTimeLimitSec = kMaxTimeLimitSec;
86
87 // Set by signal handler to stop recording.
88 static volatile bool gStopRequested = false;
89
90 // Previous signal handler state, restored after first hit.
91 static struct sigaction gOrigSigactionINT;
92 static struct sigaction gOrigSigactionHUP;
93
94
95 /*
96 * Catch keyboard interrupt signals. On receipt, the "stop requested"
97 * flag is raised, and the original handler is restored (so that, if
98 * we get stuck finishing, a second Ctrl-C will kill the process).
99 */
signalCatcher(int signum)100 static void signalCatcher(int signum)
101 {
102 gStopRequested = true;
103 switch (signum) {
104 case SIGINT:
105 case SIGHUP:
106 sigaction(SIGINT, &gOrigSigactionINT, NULL);
107 sigaction(SIGHUP, &gOrigSigactionHUP, NULL);
108 break;
109 default:
110 abort();
111 break;
112 }
113 }
114
115 /*
116 * Configures signal handlers. The previous handlers are saved.
117 *
118 * If the command is run from an interactive adb shell, we get SIGINT
119 * when Ctrl-C is hit. If we're run from the host, the local adb process
120 * gets the signal, and we get a SIGHUP when the terminal disconnects.
121 */
configureSignals()122 static status_t configureSignals() {
123 struct sigaction act;
124 memset(&act, 0, sizeof(act));
125 act.sa_handler = signalCatcher;
126 if (sigaction(SIGINT, &act, &gOrigSigactionINT) != 0) {
127 status_t err = -errno;
128 fprintf(stderr, "Unable to configure SIGINT handler: %s\n",
129 strerror(errno));
130 return err;
131 }
132 if (sigaction(SIGHUP, &act, &gOrigSigactionHUP) != 0) {
133 status_t err = -errno;
134 fprintf(stderr, "Unable to configure SIGHUP handler: %s\n",
135 strerror(errno));
136 return err;
137 }
138 signal(SIGPIPE, SIG_IGN);
139 return NO_ERROR;
140 }
141
142 /*
143 * Returns "true" if the device is rotated 90 degrees.
144 */
isDeviceRotated(int orientation)145 static bool isDeviceRotated(int orientation) {
146 return orientation != DISPLAY_ORIENTATION_0 &&
147 orientation != DISPLAY_ORIENTATION_180;
148 }
149
150 /*
151 * Configures and starts the MediaCodec encoder. Obtains an input surface
152 * from the codec.
153 */
prepareEncoder(float displayFps,sp<MediaCodec> * pCodec,sp<IGraphicBufferProducer> * pBufferProducer)154 static status_t prepareEncoder(float displayFps, sp<MediaCodec>* pCodec,
155 sp<IGraphicBufferProducer>* pBufferProducer) {
156 status_t err;
157
158 if (gVerbose) {
159 printf("Configuring recorder for %dx%d %s at %.2fMbps\n",
160 gVideoWidth, gVideoHeight, kMimeTypeAvc, gBitRate / 1000000.0);
161 fflush(stdout);
162 }
163
164 sp<AMessage> format = new AMessage;
165 format->setInt32("width", gVideoWidth);
166 format->setInt32("height", gVideoHeight);
167 format->setString("mime", kMimeTypeAvc);
168 format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque);
169 format->setInt32("bitrate", gBitRate);
170 format->setFloat("frame-rate", displayFps);
171 format->setInt32("i-frame-interval", 10);
172
173 sp<ALooper> looper = new ALooper;
174 looper->setName("screenrecord_looper");
175 looper->start();
176 ALOGV("Creating codec");
177 sp<MediaCodec> codec;
178 if (gCodecName.empty()) {
179 codec = MediaCodec::CreateByType(looper, kMimeTypeAvc, true);
180 if (codec == NULL) {
181 fprintf(stderr, "ERROR: unable to create %s codec instance\n",
182 kMimeTypeAvc);
183 return UNKNOWN_ERROR;
184 }
185 } else {
186 codec = MediaCodec::CreateByComponentName(looper, gCodecName);
187 if (codec == NULL) {
188 fprintf(stderr, "ERROR: unable to create %s codec instance\n",
189 gCodecName.c_str());
190 return UNKNOWN_ERROR;
191 }
192 }
193
194 err = codec->configure(format, NULL, NULL,
195 MediaCodec::CONFIGURE_FLAG_ENCODE);
196 if (err != NO_ERROR) {
197 fprintf(stderr, "ERROR: unable to configure %s codec at %dx%d (err=%d)\n",
198 kMimeTypeAvc, gVideoWidth, gVideoHeight, err);
199 codec->release();
200 return err;
201 }
202
203 ALOGV("Creating encoder input surface");
204 sp<IGraphicBufferProducer> bufferProducer;
205 if (gPersistentSurface) {
206 sp<PersistentSurface> surface = MediaCodec::CreatePersistentInputSurface();
207 bufferProducer = surface->getBufferProducer();
208 err = codec->setInputSurface(surface);
209 } else {
210 err = codec->createInputSurface(&bufferProducer);
211 }
212 if (err != NO_ERROR) {
213 fprintf(stderr,
214 "ERROR: unable to %s encoder input surface (err=%d)\n",
215 gPersistentSurface ? "set" : "create",
216 err);
217 codec->release();
218 return err;
219 }
220
221 ALOGV("Starting codec");
222 err = codec->start();
223 if (err != NO_ERROR) {
224 fprintf(stderr, "ERROR: unable to start codec (err=%d)\n", err);
225 codec->release();
226 return err;
227 }
228
229 ALOGV("Codec prepared");
230 *pCodec = codec;
231 *pBufferProducer = bufferProducer;
232 return 0;
233 }
234
235 /*
236 * Sets the display projection, based on the display dimensions, video size,
237 * and device orientation.
238 */
setDisplayProjection(SurfaceComposerClient::Transaction & t,const sp<IBinder> & dpy,const DisplayInfo & mainDpyInfo)239 static status_t setDisplayProjection(
240 SurfaceComposerClient::Transaction& t,
241 const sp<IBinder>& dpy,
242 const DisplayInfo& mainDpyInfo) {
243
244 // Set the region of the layer stack we're interested in, which in our
245 // case is "all of it". If the app is rotated (so that the width of the
246 // app is based on the height of the display), reverse width/height.
247 bool deviceRotated = isDeviceRotated(mainDpyInfo.orientation);
248 uint32_t sourceWidth, sourceHeight;
249 if (!deviceRotated) {
250 sourceWidth = mainDpyInfo.w;
251 sourceHeight = mainDpyInfo.h;
252 } else {
253 ALOGV("using rotated width/height");
254 sourceHeight = mainDpyInfo.w;
255 sourceWidth = mainDpyInfo.h;
256 }
257 Rect layerStackRect(sourceWidth, sourceHeight);
258
259 // We need to preserve the aspect ratio of the display.
260 float displayAspect = (float) sourceHeight / (float) sourceWidth;
261
262
263 // Set the way we map the output onto the display surface (which will
264 // be e.g. 1280x720 for a 720p video). The rect is interpreted
265 // post-rotation, so if the display is rotated 90 degrees we need to
266 // "pre-rotate" it by flipping width/height, so that the orientation
267 // adjustment changes it back.
268 //
269 // We might want to encode a portrait display as landscape to use more
270 // of the screen real estate. (If players respect a 90-degree rotation
271 // hint, we can essentially get a 720x1280 video instead of 1280x720.)
272 // In that case, we swap the configured video width/height and then
273 // supply a rotation value to the display projection.
274 uint32_t videoWidth, videoHeight;
275 uint32_t outWidth, outHeight;
276 if (!gRotate) {
277 videoWidth = gVideoWidth;
278 videoHeight = gVideoHeight;
279 } else {
280 videoWidth = gVideoHeight;
281 videoHeight = gVideoWidth;
282 }
283 if (videoHeight > (uint32_t)(videoWidth * displayAspect)) {
284 // limited by narrow width; reduce height
285 outWidth = videoWidth;
286 outHeight = (uint32_t)(videoWidth * displayAspect);
287 } else {
288 // limited by short height; restrict width
289 outHeight = videoHeight;
290 outWidth = (uint32_t)(videoHeight / displayAspect);
291 }
292 uint32_t offX, offY;
293 offX = (videoWidth - outWidth) / 2;
294 offY = (videoHeight - outHeight) / 2;
295 Rect displayRect(offX, offY, offX + outWidth, offY + outHeight);
296
297 if (gVerbose) {
298 if (gRotate) {
299 printf("Rotated content area is %ux%u at offset x=%d y=%d\n",
300 outHeight, outWidth, offY, offX);
301 fflush(stdout);
302 } else {
303 printf("Content area is %ux%u at offset x=%d y=%d\n",
304 outWidth, outHeight, offX, offY);
305 fflush(stdout);
306 }
307 }
308
309 t.setDisplayProjection(dpy,
310 gRotate ? DISPLAY_ORIENTATION_90 : DISPLAY_ORIENTATION_0,
311 layerStackRect, displayRect);
312 return NO_ERROR;
313 }
314
315 /*
316 * Configures the virtual display. When this completes, virtual display
317 * frames will start arriving from the buffer producer.
318 */
prepareVirtualDisplay(const DisplayInfo & mainDpyInfo,const sp<IGraphicBufferProducer> & bufferProducer,sp<IBinder> * pDisplayHandle)319 static status_t prepareVirtualDisplay(const DisplayInfo& mainDpyInfo,
320 const sp<IGraphicBufferProducer>& bufferProducer,
321 sp<IBinder>* pDisplayHandle) {
322 sp<IBinder> dpy = SurfaceComposerClient::createDisplay(
323 String8("ScreenRecorder"), false /*secure*/);
324
325 SurfaceComposerClient::Transaction t;
326 t.setDisplaySurface(dpy, bufferProducer);
327 setDisplayProjection(t, dpy, mainDpyInfo);
328 t.setDisplayLayerStack(dpy, 0); // default stack
329 t.apply();
330
331 *pDisplayHandle = dpy;
332
333 return NO_ERROR;
334 }
335
336 /*
337 * Runs the MediaCodec encoder, sending the output to the MediaMuxer. The
338 * input frames are coming from the virtual display as fast as SurfaceFlinger
339 * wants to send them.
340 *
341 * Exactly one of muxer or rawFp must be non-null.
342 *
343 * The muxer must *not* have been started before calling.
344 */
runEncoder(const sp<MediaCodec> & encoder,const sp<MediaMuxer> & muxer,FILE * rawFp,const sp<IBinder> & mainDpy,const sp<IBinder> & virtualDpy,uint8_t orientation)345 static status_t runEncoder(const sp<MediaCodec>& encoder,
346 const sp<MediaMuxer>& muxer, FILE* rawFp, const sp<IBinder>& mainDpy,
347 const sp<IBinder>& virtualDpy, uint8_t orientation) {
348 static int kTimeout = 250000; // be responsive on signal
349 status_t err;
350 ssize_t trackIdx = -1;
351 uint32_t debugNumFrames = 0;
352 int64_t startWhenNsec = systemTime(CLOCK_MONOTONIC);
353 int64_t endWhenNsec = startWhenNsec + seconds_to_nanoseconds(gTimeLimitSec);
354 DisplayInfo mainDpyInfo;
355
356 assert((rawFp == NULL && muxer != NULL) || (rawFp != NULL && muxer == NULL));
357
358 Vector<sp<MediaCodecBuffer> > buffers;
359 err = encoder->getOutputBuffers(&buffers);
360 if (err != NO_ERROR) {
361 fprintf(stderr, "Unable to get output buffers (err=%d)\n", err);
362 return err;
363 }
364
365 // Run until we're signaled.
366 while (!gStopRequested) {
367 size_t bufIndex, offset, size;
368 int64_t ptsUsec;
369 uint32_t flags;
370
371 if (systemTime(CLOCK_MONOTONIC) > endWhenNsec) {
372 if (gVerbose) {
373 printf("Time limit reached\n");
374 fflush(stdout);
375 }
376 break;
377 }
378
379 ALOGV("Calling dequeueOutputBuffer");
380 err = encoder->dequeueOutputBuffer(&bufIndex, &offset, &size, &ptsUsec,
381 &flags, kTimeout);
382 ALOGV("dequeueOutputBuffer returned %d", err);
383 switch (err) {
384 case NO_ERROR:
385 // got a buffer
386 if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) != 0) {
387 ALOGV("Got codec config buffer (%zu bytes)", size);
388 if (muxer != NULL) {
389 // ignore this -- we passed the CSD into MediaMuxer when
390 // we got the format change notification
391 size = 0;
392 }
393 }
394 if (size != 0) {
395 ALOGV("Got data in buffer %zu, size=%zu, pts=%" PRId64,
396 bufIndex, size, ptsUsec);
397
398 { // scope
399 ATRACE_NAME("orientation");
400 // Check orientation, update if it has changed.
401 //
402 // Polling for changes is inefficient and wrong, but the
403 // useful stuff is hard to get at without a Dalvik VM.
404 err = SurfaceComposerClient::getDisplayInfo(mainDpy,
405 &mainDpyInfo);
406 if (err != NO_ERROR) {
407 ALOGW("getDisplayInfo(main) failed: %d", err);
408 } else if (orientation != mainDpyInfo.orientation) {
409 ALOGD("orientation changed, now %d", mainDpyInfo.orientation);
410 SurfaceComposerClient::Transaction t;
411 setDisplayProjection(t, virtualDpy, mainDpyInfo);
412 t.apply();
413 orientation = mainDpyInfo.orientation;
414 }
415 }
416
417 // If the virtual display isn't providing us with timestamps,
418 // use the current time. This isn't great -- we could get
419 // decoded data in clusters -- but we're not expecting
420 // to hit this anyway.
421 if (ptsUsec == 0) {
422 ptsUsec = systemTime(SYSTEM_TIME_MONOTONIC) / 1000;
423 }
424
425 if (muxer == NULL) {
426 fwrite(buffers[bufIndex]->data(), 1, size, rawFp);
427 // Flush the data immediately in case we're streaming.
428 // We don't want to do this if all we've written is
429 // the SPS/PPS data because mplayer gets confused.
430 if ((flags & MediaCodec::BUFFER_FLAG_CODECCONFIG) == 0) {
431 fflush(rawFp);
432 }
433 } else {
434 // The MediaMuxer docs are unclear, but it appears that we
435 // need to pass either the full set of BufferInfo flags, or
436 // (flags & BUFFER_FLAG_SYNCFRAME).
437 //
438 // If this blocks for too long we could drop frames. We may
439 // want to queue these up and do them on a different thread.
440 ATRACE_NAME("write sample");
441 assert(trackIdx != -1);
442 // TODO
443 sp<ABuffer> buffer = new ABuffer(
444 buffers[bufIndex]->data(), buffers[bufIndex]->size());
445 err = muxer->writeSampleData(buffer, trackIdx,
446 ptsUsec, flags);
447 if (err != NO_ERROR) {
448 fprintf(stderr,
449 "Failed writing data to muxer (err=%d)\n", err);
450 return err;
451 }
452 }
453 debugNumFrames++;
454 }
455 err = encoder->releaseOutputBuffer(bufIndex);
456 if (err != NO_ERROR) {
457 fprintf(stderr, "Unable to release output buffer (err=%d)\n",
458 err);
459 return err;
460 }
461 if ((flags & MediaCodec::BUFFER_FLAG_EOS) != 0) {
462 // Not expecting EOS from SurfaceFlinger. Go with it.
463 ALOGI("Received end-of-stream");
464 gStopRequested = true;
465 }
466 break;
467 case -EAGAIN: // INFO_TRY_AGAIN_LATER
468 ALOGV("Got -EAGAIN, looping");
469 break;
470 case INFO_FORMAT_CHANGED: // INFO_OUTPUT_FORMAT_CHANGED
471 {
472 // Format includes CSD, which we must provide to muxer.
473 ALOGV("Encoder format changed");
474 sp<AMessage> newFormat;
475 encoder->getOutputFormat(&newFormat);
476 if (muxer != NULL) {
477 trackIdx = muxer->addTrack(newFormat);
478 ALOGV("Starting muxer");
479 err = muxer->start();
480 if (err != NO_ERROR) {
481 fprintf(stderr, "Unable to start muxer (err=%d)\n", err);
482 return err;
483 }
484 }
485 }
486 break;
487 case INFO_OUTPUT_BUFFERS_CHANGED: // INFO_OUTPUT_BUFFERS_CHANGED
488 // Not expected for an encoder; handle it anyway.
489 ALOGV("Encoder buffers changed");
490 err = encoder->getOutputBuffers(&buffers);
491 if (err != NO_ERROR) {
492 fprintf(stderr,
493 "Unable to get new output buffers (err=%d)\n", err);
494 return err;
495 }
496 break;
497 case INVALID_OPERATION:
498 ALOGW("dequeueOutputBuffer returned INVALID_OPERATION");
499 return err;
500 default:
501 fprintf(stderr,
502 "Got weird result %d from dequeueOutputBuffer\n", err);
503 return err;
504 }
505 }
506
507 ALOGV("Encoder stopping (req=%d)", gStopRequested);
508 if (gVerbose) {
509 printf("Encoder stopping; recorded %u frames in %" PRId64 " seconds\n",
510 debugNumFrames, nanoseconds_to_seconds(
511 systemTime(CLOCK_MONOTONIC) - startWhenNsec));
512 fflush(stdout);
513 }
514 return NO_ERROR;
515 }
516
517 /*
518 * Raw H.264 byte stream output requested. Send the output to stdout
519 * if desired. If the output is a tty, reconfigure it to avoid the
520 * CRLF line termination that we see with "adb shell" commands.
521 */
prepareRawOutput(const char * fileName)522 static FILE* prepareRawOutput(const char* fileName) {
523 FILE* rawFp = NULL;
524
525 if (strcmp(fileName, "-") == 0) {
526 if (gVerbose) {
527 fprintf(stderr, "ERROR: verbose output and '-' not compatible");
528 return NULL;
529 }
530 rawFp = stdout;
531 } else {
532 rawFp = fopen(fileName, "w");
533 if (rawFp == NULL) {
534 fprintf(stderr, "fopen raw failed: %s\n", strerror(errno));
535 return NULL;
536 }
537 }
538
539 int fd = fileno(rawFp);
540 if (isatty(fd)) {
541 // best effort -- reconfigure tty for "raw"
542 ALOGD("raw video output to tty (fd=%d)", fd);
543 struct termios term;
544 if (tcgetattr(fd, &term) == 0) {
545 cfmakeraw(&term);
546 if (tcsetattr(fd, TCSANOW, &term) == 0) {
547 ALOGD("tty successfully configured for raw");
548 }
549 }
550 }
551
552 return rawFp;
553 }
554
555 /*
556 * Main "do work" start point.
557 *
558 * Configures codec, muxer, and virtual display, then starts moving bits
559 * around.
560 */
recordScreen(const char * fileName)561 static status_t recordScreen(const char* fileName) {
562 status_t err;
563
564 // Configure signal handler.
565 err = configureSignals();
566 if (err != NO_ERROR) return err;
567
568 // Start Binder thread pool. MediaCodec needs to be able to receive
569 // messages from mediaserver.
570 sp<ProcessState> self = ProcessState::self();
571 self->startThreadPool();
572
573 // Get main display parameters.
574 sp<IBinder> mainDpy = SurfaceComposerClient::getBuiltInDisplay(
575 ISurfaceComposer::eDisplayIdMain);
576 DisplayInfo mainDpyInfo;
577 err = SurfaceComposerClient::getDisplayInfo(mainDpy, &mainDpyInfo);
578 if (err != NO_ERROR) {
579 fprintf(stderr, "ERROR: unable to get display characteristics\n");
580 return err;
581 }
582 if (gVerbose) {
583 printf("Main display is %dx%d @%.2ffps (orientation=%u)\n",
584 mainDpyInfo.w, mainDpyInfo.h, mainDpyInfo.fps,
585 mainDpyInfo.orientation);
586 fflush(stdout);
587 }
588
589 bool rotated = isDeviceRotated(mainDpyInfo.orientation);
590 if (gVideoWidth == 0) {
591 gVideoWidth = rotated ? mainDpyInfo.h : mainDpyInfo.w;
592 }
593 if (gVideoHeight == 0) {
594 gVideoHeight = rotated ? mainDpyInfo.w : mainDpyInfo.h;
595 }
596
597 // Configure and start the encoder.
598 sp<MediaCodec> encoder;
599 sp<FrameOutput> frameOutput;
600 sp<IGraphicBufferProducer> encoderInputSurface;
601 if (gOutputFormat != FORMAT_FRAMES && gOutputFormat != FORMAT_RAW_FRAMES) {
602 err = prepareEncoder(mainDpyInfo.fps, &encoder, &encoderInputSurface);
603
604 if (err != NO_ERROR && !gSizeSpecified) {
605 // fallback is defined for landscape; swap if we're in portrait
606 bool needSwap = gVideoWidth < gVideoHeight;
607 uint32_t newWidth = needSwap ? kFallbackHeight : kFallbackWidth;
608 uint32_t newHeight = needSwap ? kFallbackWidth : kFallbackHeight;
609 if (gVideoWidth != newWidth && gVideoHeight != newHeight) {
610 ALOGV("Retrying with 720p");
611 fprintf(stderr, "WARNING: failed at %dx%d, retrying at %dx%d\n",
612 gVideoWidth, gVideoHeight, newWidth, newHeight);
613 gVideoWidth = newWidth;
614 gVideoHeight = newHeight;
615 err = prepareEncoder(mainDpyInfo.fps, &encoder,
616 &encoderInputSurface);
617 }
618 }
619 if (err != NO_ERROR) return err;
620
621 // From here on, we must explicitly release() the encoder before it goes
622 // out of scope, or we will get an assertion failure from stagefright
623 // later on in a different thread.
624 } else {
625 // We're not using an encoder at all. The "encoder input surface" we hand to
626 // SurfaceFlinger will just feed directly to us.
627 frameOutput = new FrameOutput();
628 err = frameOutput->createInputSurface(gVideoWidth, gVideoHeight, &encoderInputSurface);
629 if (err != NO_ERROR) {
630 return err;
631 }
632 }
633
634 // Draw the "info" page by rendering a frame with GLES and sending
635 // it directly to the encoder.
636 // TODO: consider displaying this as a regular layer to avoid b/11697754
637 if (gWantInfoScreen) {
638 Overlay::drawInfoPage(encoderInputSurface);
639 }
640
641 // Configure optional overlay.
642 sp<IGraphicBufferProducer> bufferProducer;
643 sp<Overlay> overlay;
644 if (gWantFrameTime) {
645 // Send virtual display frames to an external texture.
646 overlay = new Overlay(gMonotonicTime);
647 err = overlay->start(encoderInputSurface, &bufferProducer);
648 if (err != NO_ERROR) {
649 if (encoder != NULL) encoder->release();
650 return err;
651 }
652 if (gVerbose) {
653 printf("Bugreport overlay created\n");
654 fflush(stdout);
655 }
656 } else {
657 // Use the encoder's input surface as the virtual display surface.
658 bufferProducer = encoderInputSurface;
659 }
660
661 // Configure virtual display.
662 sp<IBinder> dpy;
663 err = prepareVirtualDisplay(mainDpyInfo, bufferProducer, &dpy);
664 if (err != NO_ERROR) {
665 if (encoder != NULL) encoder->release();
666 return err;
667 }
668
669 sp<MediaMuxer> muxer = NULL;
670 FILE* rawFp = NULL;
671 switch (gOutputFormat) {
672 case FORMAT_MP4: {
673 // Configure muxer. We have to wait for the CSD blob from the encoder
674 // before we can start it.
675 err = unlink(fileName);
676 if (err != 0 && errno != ENOENT) {
677 fprintf(stderr, "ERROR: couldn't remove existing file\n");
678 abort();
679 }
680 int fd = open(fileName, O_CREAT | O_LARGEFILE | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
681 if (fd < 0) {
682 fprintf(stderr, "ERROR: couldn't open file\n");
683 abort();
684 }
685 muxer = new MediaMuxer(fd, MediaMuxer::OUTPUT_FORMAT_MPEG_4);
686 close(fd);
687 if (gRotate) {
688 muxer->setOrientationHint(90); // TODO: does this do anything?
689 }
690 break;
691 }
692 case FORMAT_H264:
693 case FORMAT_FRAMES:
694 case FORMAT_RAW_FRAMES: {
695 rawFp = prepareRawOutput(fileName);
696 if (rawFp == NULL) {
697 if (encoder != NULL) encoder->release();
698 return -1;
699 }
700 break;
701 }
702 default:
703 fprintf(stderr, "ERROR: unknown format %d\n", gOutputFormat);
704 abort();
705 }
706
707 if (gOutputFormat == FORMAT_FRAMES || gOutputFormat == FORMAT_RAW_FRAMES) {
708 // TODO: if we want to make this a proper feature, we should output
709 // an outer header with version info. Right now we never change
710 // the frame size or format, so we could conceivably just send
711 // the current frame header once and then follow it with an
712 // unbroken stream of data.
713
714 // Make the EGL context current again. This gets unhooked if we're
715 // using "--bugreport" mode.
716 // TODO: figure out if we can eliminate this
717 frameOutput->prepareToCopy();
718
719 while (!gStopRequested) {
720 // Poll for frames, the same way we do for MediaCodec. We do
721 // all of the work on the main thread.
722 //
723 // Ideally we'd sleep indefinitely and wake when the
724 // stop was requested, but this will do for now. (It almost
725 // works because wait() wakes when a signal hits, but we
726 // need to handle the edge cases.)
727 bool rawFrames = gOutputFormat == FORMAT_RAW_FRAMES;
728 err = frameOutput->copyFrame(rawFp, 250000, rawFrames);
729 if (err == ETIMEDOUT) {
730 err = NO_ERROR;
731 } else if (err != NO_ERROR) {
732 ALOGE("Got error %d from copyFrame()", err);
733 break;
734 }
735 }
736 } else {
737 // Main encoder loop.
738 err = runEncoder(encoder, muxer, rawFp, mainDpy, dpy,
739 mainDpyInfo.orientation);
740 if (err != NO_ERROR) {
741 fprintf(stderr, "Encoder failed (err=%d)\n", err);
742 // fall through to cleanup
743 }
744
745 if (gVerbose) {
746 printf("Stopping encoder and muxer\n");
747 fflush(stdout);
748 }
749 }
750
751 // Shut everything down, starting with the producer side.
752 encoderInputSurface = NULL;
753 SurfaceComposerClient::destroyDisplay(dpy);
754 if (overlay != NULL) overlay->stop();
755 if (encoder != NULL) encoder->stop();
756 if (muxer != NULL) {
757 // If we don't stop muxer explicitly, i.e. let the destructor run,
758 // it may hang (b/11050628).
759 err = muxer->stop();
760 } else if (rawFp != stdout) {
761 fclose(rawFp);
762 }
763 if (encoder != NULL) encoder->release();
764
765 return err;
766 }
767
768 /*
769 * Sends a broadcast to the media scanner to tell it about the new video.
770 *
771 * This is optional, but nice to have.
772 */
notifyMediaScanner(const char * fileName)773 static status_t notifyMediaScanner(const char* fileName) {
774 // need to do allocations before the fork()
775 String8 fileUrl("file://");
776 fileUrl.append(fileName);
777
778 const char* kCommand = "/system/bin/am";
779 const char* const argv[] = {
780 kCommand,
781 "broadcast",
782 "-a",
783 "android.intent.action.MEDIA_SCANNER_SCAN_FILE",
784 "-d",
785 fileUrl.string(),
786 NULL
787 };
788 if (gVerbose) {
789 printf("Executing:");
790 for (int i = 0; argv[i] != NULL; i++) {
791 printf(" %s", argv[i]);
792 }
793 putchar('\n');
794 fflush(stdout);
795 }
796
797 pid_t pid = fork();
798 if (pid < 0) {
799 int err = errno;
800 ALOGW("fork() failed: %s", strerror(err));
801 return -err;
802 } else if (pid > 0) {
803 // parent; wait for the child, mostly to make the verbose-mode output
804 // look right, but also to check for and log failures
805 int status;
806 pid_t actualPid = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
807 if (actualPid != pid) {
808 ALOGW("waitpid(%d) returned %d (errno=%d)", pid, actualPid, errno);
809 } else if (status != 0) {
810 ALOGW("'am broadcast' exited with status=%d", status);
811 } else {
812 ALOGV("'am broadcast' exited successfully");
813 }
814 } else {
815 if (!gVerbose) {
816 // non-verbose, suppress 'am' output
817 ALOGV("closing stdout/stderr in child");
818 int fd = open("/dev/null", O_WRONLY);
819 if (fd >= 0) {
820 dup2(fd, STDOUT_FILENO);
821 dup2(fd, STDERR_FILENO);
822 close(fd);
823 }
824 }
825 execv(kCommand, const_cast<char* const*>(argv));
826 ALOGE("execv(%s) failed: %s\n", kCommand, strerror(errno));
827 exit(1);
828 }
829 return NO_ERROR;
830 }
831
832 /*
833 * Parses a string of the form "1280x720".
834 *
835 * Returns true on success.
836 */
parseWidthHeight(const char * widthHeight,uint32_t * pWidth,uint32_t * pHeight)837 static bool parseWidthHeight(const char* widthHeight, uint32_t* pWidth,
838 uint32_t* pHeight) {
839 long width, height;
840 char* end;
841
842 // Must specify base 10, or "0x0" gets parsed differently.
843 width = strtol(widthHeight, &end, 10);
844 if (end == widthHeight || *end != 'x' || *(end+1) == '\0') {
845 // invalid chars in width, or missing 'x', or missing height
846 return false;
847 }
848 height = strtol(end + 1, &end, 10);
849 if (*end != '\0') {
850 // invalid chars in height
851 return false;
852 }
853
854 *pWidth = width;
855 *pHeight = height;
856 return true;
857 }
858
859 /*
860 * Accepts a string with a bare number ("4000000") or with a single-character
861 * unit ("4m").
862 *
863 * Returns an error if parsing fails.
864 */
parseValueWithUnit(const char * str,uint32_t * pValue)865 static status_t parseValueWithUnit(const char* str, uint32_t* pValue) {
866 long value;
867 char* endptr;
868
869 value = strtol(str, &endptr, 10);
870 if (*endptr == '\0') {
871 // bare number
872 *pValue = value;
873 return NO_ERROR;
874 } else if (toupper(*endptr) == 'M' && *(endptr+1) == '\0') {
875 *pValue = value * 1000000; // check for overflow?
876 return NO_ERROR;
877 } else {
878 fprintf(stderr, "Unrecognized value: %s\n", str);
879 return UNKNOWN_ERROR;
880 }
881 }
882
883 /*
884 * Dumps usage on stderr.
885 */
usage()886 static void usage() {
887 fprintf(stderr,
888 "Usage: screenrecord [options] <filename>\n"
889 "\n"
890 "Android screenrecord v%d.%d. Records the device's display to a .mp4 file.\n"
891 "\n"
892 "Options:\n"
893 "--size WIDTHxHEIGHT\n"
894 " Set the video size, e.g. \"1280x720\". Default is the device's main\n"
895 " display resolution (if supported), 1280x720 if not. For best results,\n"
896 " use a size supported by the AVC encoder.\n"
897 "--bit-rate RATE\n"
898 " Set the video bit rate, in bits per second. Value may be specified as\n"
899 " bits or megabits, e.g. '4000000' is equivalent to '4M'. Default %dMbps.\n"
900 "--bugreport\n"
901 " Add additional information, such as a timestamp overlay, that is helpful\n"
902 " in videos captured to illustrate bugs.\n"
903 "--time-limit TIME\n"
904 " Set the maximum recording time, in seconds. Default / maximum is %d.\n"
905 "--verbose\n"
906 " Display interesting information on stdout.\n"
907 "--help\n"
908 " Show this message.\n"
909 "\n"
910 "Recording continues until Ctrl-C is hit or the time limit is reached.\n"
911 "\n",
912 kVersionMajor, kVersionMinor, gBitRate / 1000000, gTimeLimitSec
913 );
914 }
915
916 /*
917 * Parses args and kicks things off.
918 */
main(int argc,char * const argv[])919 int main(int argc, char* const argv[]) {
920 static const struct option longOptions[] = {
921 { "help", no_argument, NULL, 'h' },
922 { "verbose", no_argument, NULL, 'v' },
923 { "size", required_argument, NULL, 's' },
924 { "bit-rate", required_argument, NULL, 'b' },
925 { "time-limit", required_argument, NULL, 't' },
926 { "bugreport", no_argument, NULL, 'u' },
927 // "unofficial" options
928 { "show-device-info", no_argument, NULL, 'i' },
929 { "show-frame-time", no_argument, NULL, 'f' },
930 { "rotate", no_argument, NULL, 'r' },
931 { "output-format", required_argument, NULL, 'o' },
932 { "codec-name", required_argument, NULL, 'N' },
933 { "monotonic-time", no_argument, NULL, 'm' },
934 { "persistent-surface", no_argument, NULL, 'p' },
935 { NULL, 0, NULL, 0 }
936 };
937
938 while (true) {
939 int optionIndex = 0;
940 int ic = getopt_long(argc, argv, "", longOptions, &optionIndex);
941 if (ic == -1) {
942 break;
943 }
944
945 switch (ic) {
946 case 'h':
947 usage();
948 return 0;
949 case 'v':
950 gVerbose = true;
951 break;
952 case 's':
953 if (!parseWidthHeight(optarg, &gVideoWidth, &gVideoHeight)) {
954 fprintf(stderr, "Invalid size '%s', must be width x height\n",
955 optarg);
956 return 2;
957 }
958 if (gVideoWidth == 0 || gVideoHeight == 0) {
959 fprintf(stderr,
960 "Invalid size %ux%u, width and height may not be zero\n",
961 gVideoWidth, gVideoHeight);
962 return 2;
963 }
964 gSizeSpecified = true;
965 break;
966 case 'b':
967 if (parseValueWithUnit(optarg, &gBitRate) != NO_ERROR) {
968 return 2;
969 }
970 if (gBitRate < kMinBitRate || gBitRate > kMaxBitRate) {
971 fprintf(stderr,
972 "Bit rate %dbps outside acceptable range [%d,%d]\n",
973 gBitRate, kMinBitRate, kMaxBitRate);
974 return 2;
975 }
976 break;
977 case 't':
978 gTimeLimitSec = atoi(optarg);
979 if (gTimeLimitSec == 0 || gTimeLimitSec > kMaxTimeLimitSec) {
980 fprintf(stderr,
981 "Time limit %ds outside acceptable range [1,%d]\n",
982 gTimeLimitSec, kMaxTimeLimitSec);
983 return 2;
984 }
985 break;
986 case 'u':
987 gWantInfoScreen = true;
988 gWantFrameTime = true;
989 break;
990 case 'i':
991 gWantInfoScreen = true;
992 break;
993 case 'f':
994 gWantFrameTime = true;
995 break;
996 case 'r':
997 // experimental feature
998 gRotate = true;
999 break;
1000 case 'o':
1001 if (strcmp(optarg, "mp4") == 0) {
1002 gOutputFormat = FORMAT_MP4;
1003 } else if (strcmp(optarg, "h264") == 0) {
1004 gOutputFormat = FORMAT_H264;
1005 } else if (strcmp(optarg, "frames") == 0) {
1006 gOutputFormat = FORMAT_FRAMES;
1007 } else if (strcmp(optarg, "raw-frames") == 0) {
1008 gOutputFormat = FORMAT_RAW_FRAMES;
1009 } else {
1010 fprintf(stderr, "Unknown format '%s'\n", optarg);
1011 return 2;
1012 }
1013 break;
1014 case 'N':
1015 gCodecName = optarg;
1016 break;
1017 case 'm':
1018 gMonotonicTime = true;
1019 break;
1020 case 'p':
1021 gPersistentSurface = true;
1022 break;
1023 default:
1024 if (ic != '?') {
1025 fprintf(stderr, "getopt_long returned unexpected value 0x%x\n", ic);
1026 }
1027 return 2;
1028 }
1029 }
1030
1031 if (optind != argc - 1) {
1032 fprintf(stderr, "Must specify output file (see --help).\n");
1033 return 2;
1034 }
1035
1036 const char* fileName = argv[optind];
1037 if (gOutputFormat == FORMAT_MP4) {
1038 // MediaMuxer tries to create the file in the constructor, but we don't
1039 // learn about the failure until muxer.start(), which returns a generic
1040 // error code without logging anything. We attempt to create the file
1041 // now for better diagnostics.
1042 int fd = open(fileName, O_CREAT | O_RDWR, 0644);
1043 if (fd < 0) {
1044 fprintf(stderr, "Unable to open '%s': %s\n", fileName, strerror(errno));
1045 return 1;
1046 }
1047 close(fd);
1048 }
1049
1050 status_t err = recordScreen(fileName);
1051 if (err == NO_ERROR) {
1052 // Try to notify the media scanner. Not fatal if this fails.
1053 notifyMediaScanner(fileName);
1054 }
1055 ALOGD(err == NO_ERROR ? "success" : "failed");
1056 return (int) err;
1057 }
1058