avcodec/mediacodecdec: add workaround for buggy amlogic mpeg2 decoder
authorAman Gupta <aman@tmm1.net>
Thu, 26 Apr 2018 18:51:15 +0000 (11:51 -0700)
committerAman Gupta <aman@tmm1.net>
Fri, 4 May 2018 18:53:44 +0000 (11:53 -0700)
I tested the previous mediacodec changes on seven different Android
TV devices, with both mpeg2 and h264 content. All except one worked
as expected. The exception was the MiBox3 running Android 6.0.1,
where playback would freeze on a frame every few seconds. I tested
two other AMLogic devices with newer Android versions that did not
show the same problem. H264 decoding on the MiBox3 was also not affected,
so this workaround applies only to OMX.amlogic.mpeg2.decoder.awesome
on Android API22.

There is a rumor that Xiaomi is planning to release Android Oreo for
the MiBox3, so I will revisit in a few months to confirm whether this
is specific to os/driver version or the chipset used in that device.

Signed-off-by: Aman Gupta <aman@tmm1.net>
Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com>
libavcodec/mediacodecdec.c

index 2ac22dd..3a4240a 100644 (file)
@@ -48,6 +48,7 @@ typedef struct MediaCodecH264DecContext {
     AVPacket buffered_pkt;
 
     int delay_flush;
+    int amlogic_mpeg2_api23_workaround;
 
 } MediaCodecH264DecContext;
 
@@ -287,6 +288,7 @@ static int common_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
 static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
 {
     int ret;
+    int sdk_int;
 
     const char *codec_mime = NULL;
 
@@ -377,7 +379,17 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx)
         goto done;
     }
 
-    av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret);
+    av_log(avctx, AV_LOG_INFO,
+           "MediaCodec started successfully: codec = %s, ret = %d\n",
+           s->ctx->codec_name, ret);
+
+    sdk_int = ff_Build_SDK_INT(avctx);
+    if (sdk_int <= 23 &&
+        strcmp(s->ctx->codec_name, "OMX.amlogic.mpeg2.decoder.awesome") == 0) {
+        av_log(avctx, AV_LOG_INFO, "Enabling workaround for %s on API=%d\n",
+               s->ctx->codec_name, sdk_int);
+        s->amlogic_mpeg2_api23_workaround = 1;
+    }
 
 done:
     if (format) {
@@ -434,8 +446,12 @@ static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
                 return ret;
             }
 
-            /* poll for space again */
-            continue;
+            if (s->amlogic_mpeg2_api23_workaround && s->buffered_pkt.size <= 0) {
+                /* fallthrough to fetch next packet regardless of input buffer space */
+            } else {
+                /* poll for space again */
+                continue;
+            }
         }
 
         /* fetch new packet or eof */