stagefright: add -P pixelformat flag for -t (thumbnail) option in stagefright
when -P is supplied the output is in raw format for thumbnail, and it gets
output to /sdcard/out.raw (instead of /sdcard/out.jpg)
Supported -P values:
-P 1 :: RGBA_8888 (R is first byte)
-P 4 :: RGBA_565
-P 5 :: BGRA_8888 (B is first byte)
-P 43 :: RGBA_1010102
-P -43 :: RGBA_1010102 saved as RGBA_8888
(this mode is added because many tools don't support RGBA_1010102)
Use as:
stagefright -t -P 4 <file>
Bug: 216707498
Change-Id: Ib3fa6f332427ad5148903fae0c93640a4861be41
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index c430f05..6d1263e 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -70,6 +70,10 @@
using namespace android;
+namespace {
+ constexpr static int PIXEL_FORMAT_RGBA_1010102_AS_8888 = -HAL_PIXEL_FORMAT_RGBA_1010102;
+}
+
static long gNumRepetitions;
static long gMaxNumFrames; // 0 means decode all available.
static long gReproduceBug; // if not -1.
@@ -629,7 +633,14 @@
fprintf(stderr, " -m max-number-of-frames-to-decode in each pass\n");
fprintf(stderr, " -b bug to reproduce\n");
fprintf(stderr, " -i(nfo) dump codec info (profiles and color formats supported, details)\n");
- fprintf(stderr, " -t(humbnail) extract video thumbnail or album art\n");
+ fprintf(stderr, " -t(humbnail) extract video thumbnail or album art (/sdcard/out.jpg)\n");
+ fprintf(stderr, " -P(ixelFormat) pixel format to use for raw thumbnail "
+ "(/sdcard/out.raw)\n");
+ fprintf(stderr, " %d: RGBA_565\n", HAL_PIXEL_FORMAT_RGB_565);
+ fprintf(stderr, " %d: RGBA_8888\n", HAL_PIXEL_FORMAT_RGBA_8888);
+ fprintf(stderr, " %d: BGRA_8888\n", HAL_PIXEL_FORMAT_BGRA_8888);
+ fprintf(stderr, " %d: RGBA_1010102\n", HAL_PIXEL_FORMAT_RGBA_1010102);
+ fprintf(stderr, " %d: RGBA_1010102 as RGBA_8888\n", PIXEL_FORMAT_RGBA_1010102_AS_8888);
fprintf(stderr, " -s(oftware) prefer software codec\n");
fprintf(stderr, " -r(hardware) force to use hardware codec\n");
fprintf(stderr, " -o playback audio\n");
@@ -787,6 +798,7 @@
bool useSurfaceTexAlloc = false;
bool dumpStream = false;
bool dumpPCMStream = false;
+ int32_t pixelFormat = 0; // thumbnail pixel format
String8 dumpStreamFilename;
gNumRepetitions = 1;
gMaxNumFrames = 0;
@@ -800,7 +812,7 @@
sp<android::ALooper> looper;
int res;
- while ((res = getopt(argc, argv, "vhaqn:lm:b:itsrow:kN:xSTd:D:")) >= 0) {
+ while ((res = getopt(argc, argv, "vhaqn:lm:b:itsrow:kN:xSTd:D:P:")) >= 0) {
switch (res) {
case 'a':
{
@@ -841,6 +853,7 @@
break;
}
+ case 'P':
case 'm':
case 'n':
case 'b':
@@ -856,6 +869,8 @@
gNumRepetitions = x;
} else if (res == 'm') {
gMaxNumFrames = x;
+ } else if (res == 'P') {
+ pixelFormat = x;
} else {
CHECK_EQ(res, 'b');
gReproduceBug = x;
@@ -978,24 +993,71 @@
close(fd);
fd = -1;
+ uint32_t retrieverPixelFormat = HAL_PIXEL_FORMAT_RGB_565;
+ if (pixelFormat == PIXEL_FORMAT_RGBA_1010102_AS_8888) {
+ retrieverPixelFormat = HAL_PIXEL_FORMAT_RGBA_1010102;
+ } else if (pixelFormat) {
+ retrieverPixelFormat = pixelFormat;
+ }
sp<IMemory> mem =
retriever->getFrameAtTime(-1,
MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC,
- HAL_PIXEL_FORMAT_RGB_565,
- false /*metaOnly*/);
+ retrieverPixelFormat, false /*metaOnly*/);
if (mem != NULL) {
failed = false;
- printf("getFrameAtTime(%s) => OK\n", filename);
+ printf("getFrameAtTime(%s) format=%d => OK\n", filename, retrieverPixelFormat);
VideoFrame *frame = (VideoFrame *)mem->unsecurePointer();
- CHECK_EQ(writeJpegFile("/sdcard/out.jpg",
- frame->getFlattenedData(),
- frame->mWidth, frame->mHeight), 0);
+ if (pixelFormat) {
+ int bpp = 0;
+ switch (pixelFormat) {
+ case HAL_PIXEL_FORMAT_RGB_565:
+ bpp = 2;
+ break;
+ case PIXEL_FORMAT_RGBA_1010102_AS_8888:
+ // convert RGBA_1010102 to RGBA_8888
+ {
+ uint32_t *data = (uint32_t *)frame->getFlattenedData();
+ uint32_t *end = data + frame->mWidth * frame->mHeight;
+ for (; data < end; ++data) {
+ *data =
+ // pick out 8-bit R, G, B values and move them to the
+ // correct position
+ ( (*data & 0x3fc) >> 2) | // R
+ ( (*data & 0xff000) >> 4) | // G
+ ( (*data & 0x3fc00000) >> 6) | // B
+ // pick out 2-bit A and expand to 8-bits
+ (((*data & 0xc0000000) >> 6) * 0x55);
+ }
+ }
+
+ FALLTHROUGH_INTENDED;
+
+ case HAL_PIXEL_FORMAT_RGBA_1010102:
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_BGRA_8888:
+ bpp = 4;
+ break;
+ }
+ if (bpp) {
+ FILE *out = fopen("/sdcard/out.raw", "wb");
+ fwrite(frame->getFlattenedData(), bpp * frame->mWidth, frame->mHeight, out);
+ fclose(out);
+
+ printf("write out %d x %d x %dbpp\n", frame->mWidth, frame->mHeight, bpp);
+ } else {
+ printf("unknown pixel format.\n");
+ }
+ } else {
+ CHECK_EQ(writeJpegFile("/sdcard/out.jpg",
+ frame->getFlattenedData(),
+ frame->mWidth, frame->mHeight), 0);
+ }
}
- {
+ if (!pixelFormat) {
mem = retriever->extractAlbumArt();
if (mem != NULL) {