dji-sdk / Mobile-SDK-Android

DJI Mobile SDK for Android: http://developer.dji.com/mobile-sdk/
Other
994 stars 581 forks source link

Pixel 6a + Android 12 -> no camera feed #1194

Open jeryini opened 2 years ago

jeryini commented 2 years ago

Hardware used:

In the release notes for 4.16.1 version, it was specified:

Video stream cannot be displayed on pixel 6 mobile phone: Fixed.

But after testing it with various DJI examples (Mobile-UXSDK, Mobile UXSDK Beta) using the latest 4.16.2 SDK version running it on the Pixel 6a (6a version, not the normal 6 version), I don't get the video feed. Though it happened once that the image appeared but froze immediately. Enabling YUV data mode and checking if onYuvDataReceived is being called also shows no callbacks being made.

Could someone with Pixel 6a try to reproduce this bug?

DJI-William commented 2 years ago

Known issue, we will fix in 4.16.4 version, a temp solution is change another phone.

jeryini commented 2 years ago

Understand, looking forward to the fix. Is there any timeline when 4.16.4 version will be available?

jeryini commented 2 years ago

Are you perhaps aware of other phone models that have the same issue? As we would like to for now exclude those phone models as supported on the Google Play store until DJI provides a fix. Due to this bug we're getting really bad reviews and would really help us understand which other phone models have the same issue.

DJI-William commented 2 years ago

As far as I know, Google Pixel 5A, 6A and Samsung Tab S7 FE has this problem, this is because of their special chipset. There is no timeline for 4.16.4 now, probs in next year.

Kubessandra commented 2 years ago

On Pixel 7

You can take the frame from the VideoFeeder datalistener in h264 and decode them with a MediaCodec, you just need to change the codec used by default by the Pixel 7 (c2.enyxos.h264.decoder, hardware decoder)

I made it work by changing the Hardware decoder: "c2.enyxos.h264.decoder" to "OMX.google.h264.decoder"

Here is my mediaCodecSetup

  private void setupMediaCodec(byte[] spsUnit) {
        Log.d(TAG, "Setup media codec");
        MediaFormat format = MediaFormat.createVideoFormat("video/avc", current_width, current_height);
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
                MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
        format.setByteBuffer("csd-0", ByteBuffer.wrap(spsUnit));
        try {
            String decoderName = new MediaCodecList(MediaCodecList.ALL_CODECS).findDecoderForFormat(format);

            // Patch, hardware decoder for Pixel 7 not working, switch to software decoder.
            if (decoderName.contains("c2.exynos.h264.decoder")) {
                decoderName = "OMX.google.h264.decoder";
            }

            m_codec = MediaCodec.createByCodecName(decoderName);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        m_codec.configure(format, null, null, 0);
        m_codec.start();
    }
jeryini commented 2 years ago

As far as I know, Google Pixel 5A, 6A and Samsung Tab S7 FE has this problem, this is because of their special chipset. There is no timeline for 4.16.4 now, probs in next year.

Hello @DJI-William !

Just noticed that 4.16.4 was released three days ago but under bug fixes it only specifies a fix for US RID function. That probably means that version does not have the mentioned fix for missing video?

Kubessandra commented 2 years ago

Just noticed that 4.16.4 was released three days ago but under bug fixes it only specifies a fix for US RID function. That probably means that version does not have the mentioned fix for missing video?

I tried it, the issue is still there

DJI-William commented 2 years ago

4.16.4 didn't contain the bug fix, this bug will be fixed in 4.16.5.

mitchrsm commented 1 year ago

Is there any estimate release date for 4.16.5 ?

DJI-William commented 1 year ago

At least after Chinese New Year, about Feb to March.

brien-crean commented 1 year ago

@DJI-William is there any updated timeline on an update for Android SDK 4.16.5 now that the version 5 SDK has been updated? We're seeing quite a few of our users with this issue.

Thanks

petered commented 1 year ago

Ooof - just got a shiny new pixel 6a and got hit with this.

@DJI-William - I hope you all had a great Chinese new year. Rabbits are known for being speedy and responsive, perhaps in honour of the year of the Rabbit, we can have a 4.16.5 SDK with the fix?

dji-dev commented 1 year ago

Agent comment from yating.liao in Zendesk ticket #72453:

I will send your comments back to the team and try to push the issue forward. However, it is not possible to determine a fix time yet.

°°°

brien-crean commented 1 year ago

@Kubessandra I'm trying to implement the solution you posted. Switching to a software decoder. How do I obtain the spsUnit?

private void setupMediaCodec(byte[] spsUnit) {}

Also with this solution do I need to attach the decoded video frames to a Surface?

brien-crean commented 1 year ago

I tried to create a custom H264Parser to extract the sps data from the videoBuffer as it comes through, but I only get Nal type 1 and 6. It never finds NAL type 7 so cannot find the SPS data. Is there some other way that this data should be extracted?

val h264Parser = H264Parser()

VideoDataListener { videoBuffer: ByteArray?, size: Int ->
  val spsData = h264Parser.extractSPS(videoBuffer, size)
  Log.d("DEBUG", "spsData $spsData")
}

class H264Parser {
    fun extractSPS(videoBuffer: ByteArray?, size: Int): ByteArray? {
        // Check if the videoBuffer is valid and contains data
        if (videoBuffer == null || size <= 0) {
            return null
        }

        // Create a list to store SPS NAL units
        val spsList = ArrayList<ByteArray>()

        // Parse the videoBuffer to identify and extract SPS NAL units
        var index = 0
        while (index < size - 4) {
            if (videoBuffer[index] == 0.toByte() &&
                    videoBuffer[index + 1] == 0.toByte() &&
                    videoBuffer[index + 2] == 0.toByte() &&
                    videoBuffer[index + 3] == 1.toByte()
            ) {
                Log.d("DEBUG", "FOUND NAL UNIT")
                // Found a NAL unit delimiter (start code)
                var endIndex = 0
                val nalType = videoBuffer[index + 4] and 0x1F.toByte() // Extract NAL unit type
                Log.d("DEBUG", "NAL TYPE $nalType")
                if (nalType == 7.toByte()) {
                    // NAL unit type 7 corresponds to SPS
                    val startIndex = index + 4
                    // Find the end of the SPS NAL unit
                    endIndex = index + 4
                    while (endIndex < size - 1 && !(videoBuffer[endIndex] == 0.toByte() && videoBuffer[endIndex + 1] == 0.toByte() && videoBuffer[endIndex + 2] == 0.toByte() && videoBuffer[endIndex + 3] == 1.toByte())) {
                        endIndex++
                    }
                    // Extract the SPS data
                    val spsData = videoBuffer.copyOfRange(startIndex, endIndex)
                    spsList.add(spsData)
                } else {
                    Log.d("DEBUG", "NAL UNIT NOT SPS")
                }
                index = endIndex
            } else {
                index++
            }
        }

        if (spsList.isEmpty()) {
            return null
        }

        // Combine all extracted SPS NAL units into a single byte array
        return spsList.reduce { acc, bytes -> acc + bytes }
    }
}
Kubessandra commented 1 year ago

Here is how I implemented it on react-native-webrtc

You can also find how I used the sdk on react-native Here

dji-dev commented 1 year ago

Agent comment from yating.liao in Zendesk ticket #72453:

I'm sorry for the long wait. The issue with MSDK 4.X not being able to render videos on some models has been reported and the fix code has been submitted. It will be released with the official version 4.17.

°°°