3535static void usage (const char *me) {
3636 fprintf (stderr, " usage: %s [-a] use audio\n "
3737 " \t\t [-v] use video\n "
38- " \t\t [-p] playback\n " , me);
38+ " \t\t [-p] playback\n "
39+ " \t\t [-S] allocate buffers from a surface\n " , me);
3940
4041 exit (1 );
4142}
@@ -49,6 +50,9 @@ struct CodecState {
4950 Vector<sp<ABuffer> > mInBuffers ;
5051 Vector<sp<ABuffer> > mOutBuffers ;
5152 bool mSawOutputEOS ;
53+ int64_t mNumBuffersDecoded ;
54+ int64_t mNumBytesDecoded ;
55+ bool mIsAudio ;
5256};
5357
5458} // namespace android
@@ -57,9 +61,12 @@ static int decode(
5761 const android::sp<android::ALooper> &looper,
5862 const char *path,
5963 bool useAudio,
60- bool useVideo) {
64+ bool useVideo,
65+ const android::sp<android::Surface> &surface) {
6166 using namespace android ;
6267
68+ static int64_t kTimeout = 500ll ;
69+
6370 sp<NuMediaExtractor> extractor = new NuMediaExtractor;
6471 if (extractor->setDataSource (path) != OK) {
6572 fprintf (stderr, " unable to instantiate extractor.\n " );
@@ -78,11 +85,12 @@ static int decode(
7885 AString mime;
7986 CHECK (format->findString (" mime" , &mime));
8087
81- if (useAudio && !haveAudio
82- && !strncasecmp (mime.c_str (), " audio/" , 6 )) {
88+ bool isAudio = !strncasecmp (mime.c_str (), " audio/" , 6 );
89+ bool isVideo = !strncasecmp (mime.c_str (), " video/" , 6 );
90+
91+ if (useAudio && !haveAudio && isAudio) {
8392 haveAudio = true ;
84- } else if (useVideo && !haveVideo
85- && !strncasecmp (mime.c_str (), " video/" , 6 )) {
93+ } else if (useVideo && !haveVideo && isVideo) {
8694 haveVideo = true ;
8795 } else {
8896 continue ;
@@ -96,13 +104,17 @@ static int decode(
96104 CodecState *state =
97105 &stateByTrack.editValueAt (stateByTrack.add (i, CodecState ()));
98106
107+ state->mNumBytesDecoded = 0 ;
108+ state->mNumBuffersDecoded = 0 ;
109+ state->mIsAudio = isAudio;
110+
99111 state->mCodec = MediaCodec::CreateByType (
100112 looper, mime.c_str (), false /* encoder */ );
101113
102114 CHECK (state->mCodec != NULL );
103115
104116 err = state->mCodec ->configure (
105- format, NULL /* surfaceTexture */ , 0 /* flags */ );
117+ format, isVideo ? surface : NULL , 0 /* flags */ );
106118
107119 CHECK_EQ (err, (status_t )OK);
108120
@@ -122,6 +134,8 @@ static int decode(
122134
123135 CHECK (!stateByTrack.isEmpty ());
124136
137+ int64_t startTimeUs = ALooper::GetNowUs ();
138+
125139 for (size_t i = 0 ; i < stateByTrack.size (); ++i) {
126140 CodecState *state = &stateByTrack.editValueAt (i);
127141
@@ -137,13 +151,7 @@ static int decode(
137151
138152 while (state->mCSDIndex < state->mCSD .size ()) {
139153 size_t index;
140- status_t err = codec->dequeueInputBuffer (&index);
141-
142- if (err == -EAGAIN) {
143- usleep (10000 );
144- continue ;
145- }
146-
154+ status_t err = codec->dequeueInputBuffer (&index, -1ll );
147155 CHECK_EQ (err, (status_t )OK);
148156
149157 const sp<ABuffer> &srcBuffer =
@@ -179,7 +187,7 @@ static int decode(
179187
180188 for (;;) {
181189 size_t index;
182- err = state->mCodec ->dequeueInputBuffer (&index);
190+ err = state->mCodec ->dequeueInputBuffer (&index, kTimeout );
183191
184192 if (err == -EAGAIN) {
185193 continue ;
@@ -204,7 +212,7 @@ static int decode(
204212 CodecState *state = &stateByTrack.editValueFor (trackIndex);
205213
206214 size_t index;
207- err = state->mCodec ->dequeueInputBuffer (&index);
215+ err = state->mCodec ->dequeueInputBuffer (&index, kTimeout );
208216
209217 if (err == OK) {
210218 ALOGV (" filling input buffer %d" , index);
@@ -261,12 +269,15 @@ static int decode(
261269 uint32_t flags;
262270 status_t err = state->mCodec ->dequeueOutputBuffer (
263271 &index, &offset, &size, &presentationTimeUs, &flags,
264- 10000ll );
272+ kTimeout );
265273
266274 if (err == OK) {
267275 ALOGV (" draining output buffer %d, time = %lld us" ,
268276 index, presentationTimeUs);
269277
278+ ++state->mNumBuffersDecoded ;
279+ state->mNumBytesDecoded += size;
280+
270281 err = state->mCodec ->releaseOutputBuffer (index);
271282 CHECK_EQ (err, (status_t )OK);
272283
@@ -292,10 +303,27 @@ static int decode(
292303 }
293304 }
294305
306+ int64_t elapsedTimeUs = ALooper::GetNowUs () - startTimeUs;
307+
295308 for (size_t i = 0 ; i < stateByTrack.size (); ++i) {
296309 CodecState *state = &stateByTrack.editValueAt (i);
297310
298311 CHECK_EQ ((status_t )OK, state->mCodec ->release ());
312+
313+ if (state->mIsAudio ) {
314+ printf (" track %d: %lld bytes received. %.2f KB/sec\n " ,
315+ i,
316+ state->mNumBytesDecoded ,
317+ state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
318+ } else {
319+ printf (" track %d: %lld frames decoded, %.2f fps. %lld bytes "
320+ " received. %.2f KB/sec\n " ,
321+ i,
322+ state->mNumBuffersDecoded ,
323+ state->mNumBuffersDecoded * 1E6 / elapsedTimeUs,
324+ state->mNumBytesDecoded ,
325+ state->mNumBytesDecoded * 1E6 / 1024 / elapsedTimeUs);
326+ }
299327 }
300328
301329 return 0 ;
@@ -309,9 +337,10 @@ int main(int argc, char **argv) {
309337 bool useAudio = false ;
310338 bool useVideo = false ;
311339 bool playback = false ;
340+ bool useSurface = false ;
312341
313342 int res;
314- while ((res = getopt (argc, argv, " havp " )) >= 0 ) {
343+ while ((res = getopt (argc, argv, " havpS " )) >= 0 ) {
315344 switch (res) {
316345 case ' a' :
317346 {
@@ -331,6 +360,12 @@ int main(int argc, char **argv) {
331360 break ;
332361 }
333362
363+ case ' S' :
364+ {
365+ useSurface = true ;
366+ break ;
367+ }
368+
334369 case ' ?' :
335370 case ' h' :
336371 default :
@@ -358,23 +393,26 @@ int main(int argc, char **argv) {
358393 sp<ALooper> looper = new ALooper;
359394 looper->start ();
360395
361- if (playback) {
362- sp<SurfaceComposerClient> composerClient = new SurfaceComposerClient;
396+ sp<SurfaceComposerClient> composerClient;
397+ sp<SurfaceControl> control;
398+ sp<Surface> surface;
399+
400+ if (playback || (useSurface && useVideo)) {
401+ composerClient = new SurfaceComposerClient;
363402 CHECK_EQ (composerClient->initCheck (), (status_t )OK);
364403
365404 ssize_t displayWidth = composerClient->getDisplayWidth (0 );
366405 ssize_t displayHeight = composerClient->getDisplayHeight (0 );
367406
368407 ALOGV (" display is %ld x %ld\n " , displayWidth, displayHeight);
369408
370- sp<SurfaceControl> control =
371- composerClient->createSurface (
372- String8 (" A Surface" ),
373- 0 ,
374- displayWidth,
375- displayHeight,
376- PIXEL_FORMAT_RGB_565,
377- 0 );
409+ control = composerClient->createSurface (
410+ String8 (" A Surface" ),
411+ 0 ,
412+ displayWidth,
413+ displayHeight,
414+ PIXEL_FORMAT_RGB_565,
415+ 0 );
378416
379417 CHECK (control != NULL );
380418 CHECK (control->isValid ());
@@ -384,9 +422,11 @@ int main(int argc, char **argv) {
384422 CHECK_EQ (control->show (), (status_t )OK);
385423 SurfaceComposerClient::closeGlobalTransaction ();
386424
387- sp<Surface> surface = control->getSurface ();
425+ surface = control->getSurface ();
388426 CHECK (surface != NULL );
427+ }
389428
429+ if (playback) {
390430 sp<SimplePlayer> player = new SimplePlayer;
391431 looper->registerHandler (player);
392432
@@ -396,10 +436,12 @@ int main(int argc, char **argv) {
396436 sleep (60 );
397437 player->stop ();
398438 player->reset ();
439+ } else {
440+ decode (looper, argv[0 ], useAudio, useVideo, surface);
441+ }
399442
443+ if (playback || (useSurface && useVideo)) {
400444 composerClient->dispose ();
401- } else {
402- decode (looper, argv[0 ], useAudio, useVideo);
403445 }
404446
405447 looper->stop ();
0 commit comments