penfeizhou / APNG4Android

Android animation support for APNG & Animated WebP & Gif & Animated AVIF, High performance
Apache License 2.0
579 stars 76 forks source link

'Frame.frameDuration' is null #160

Closed KishorJena closed 2 years ago

KishorJena commented 2 years ago

New Issue Checklist

Issue Info

Info Value
Device Info Redmi Note 7 Pro
System Version 10.0
APNG4Android Library Version 2.23.0
Repro rate (100%)
Repro with our demo project -
Demo project link -

Issue Description and Steps

Although the first frame is saved as file properly. But the frameCount is 0 and cannot get Frame.frameDuration for first frame at least.

I wanted to iterate through each frame but framecount is 0 so stuck here.

Exception: Attempt to read from field 'int com.github.penfeizhou.animation.decode.Frame.frameDuration' on a null object reference
WebPDecoder decoder = new WebPDecoder(new FileLoader(path),null);

  if (decoder != null){

    Bitmap bm = decoder.getFrameBitmap(0);
    // saveBitmap(bm);
    // first frame is saved succefully...

    // but here getFrameCount is 0 and invoking getFrame() causes error 
    int frameCount = decoder.getFrameCount();
    int frameDuration = decoder.getFrame(0).frameDuration;
  }        

also tried this way. But still zero frame count and null getFrame()

FrameSeqDecoder decoder = WebPDrawable.fromFile(path).getFrameSeqDecoder();
WebPDecoder decoder = WebPDrawable.fromFile(path).getFrameSeqDecoder();
KishorJena commented 2 years ago

@jingpeng @penfeizhou please help

KishorJena commented 2 years ago

I wonder what am I missing. I did simple thing. Still getting 0 frameCount and Frame is null while.

I was observing classe FrameSeqDecoder as I am geeting it by invoking getFrameSeqDecoder(). https://github.com/penfeizhou/APNG4Android/blob/7b9c5e6b5ee0b9d2ac8b488711916e94c51a06d7/frameanimation/src/main/java/com/github/penfeizhou/animation/decode/FrameSeqDecoder.java#L42

getFrameCount is just size of List<Frame> frame But I could not find any code line in the class which adds frames to List frame.

getFrame() simply returning frame from List of frame by this.frames.get(index), if no frames are added then ofcourse it will return null

and that's what happening with me.

I am not sure just doubting. I am sure I am invoking methods in wrong way that's why facing this issue. Although I can get bitmap from getframeBitmap() Please suggest how to initialise in right way so that I can get frames and duration.

KishorJena commented 2 years ago

I wonder what am I missing. I did simple thing. Still getting 0 frameCount and Frame is null while.

I was observing classe FrameSeqDecoder as I am geeting it by invoking getFrameSeqDecoder().

https://github.com/penfeizhou/APNG4Android/blob/7b9c5e6b5ee0b9d2ac8b488711916e94c51a06d7/frameanimation/src/main/java/com/github/penfeizhou/animation/decode/FrameSeqDecoder.java#L42

getFrameCount is just size of List<Frame> frame But I could not find any code line in the class which adds frames to List frame.

getFrame() simply returning frame from List of frame by this.frames.get(index), if no frames are added then ofcourse it will return null

and that's what happening with me.

I am not sure just doubting. I am sure I am invoking methods in wrong way that's why facing this issue. Although I can get bitmap from getframeBitmap() Please suggest how to initialise in write way so that I can get frames and duration.

ok frames are being added in Decoder class https://github.com/penfeizhou/APNG4Android/blob/d0bf5b268b800648de0549c4a3f73b9444b4e440/awebp/src/main/java/com/github/penfeizhou/animation/webp/decode/WebPDecoder.java#L102

Now I am clueless why Frame is null.

penfeizhou commented 2 years ago

The decoding operation is asynchronous. If you do not need showing drawable into imagview, please start and stop decoder manually. Following is example codes.

            final FrameSeqDecoder decoder = drawable.getFrameSeqDecoder();
            decoder.addRenderListener(new FrameSeqDecoder.RenderListener() {
                @Override
                public void onStart() {
                    int count = decoder.getFrameCount();
                    Log.d("TEST", "Frame count is " + count);
                    // Add codes here
                }

                @Override
                public void onRender(ByteBuffer byteBuffer) {

                }

                @Override
                public void onEnd() {

                }
            });
            decoder.start();
            // After what's done, stop to avoid memory leak.
            decoder.stop();
KishorJena commented 2 years ago

The decoding operation is asynchronous. If you do not need showing drawable into imagview, please start and stop decoder manually. Following is example codes.

            final FrameSeqDecoder decoder = drawable.getFrameSeqDecoder();
            decoder.addRenderListener(new FrameSeqDecoder.RenderListener() {
                @Override
                public void onStart() {
                    int count = decoder.getFrameCount();
                    Log.d("TEST", "Frame count is " + count);
                    // Add codes here
                }

                @Override
                public void onRender(ByteBuffer byteBuffer) {

                }

                @Override
                public void onEnd() {

                }
            });
            decoder.start();
            // After what's done, stop to avoid memory leak.
            decoder.stop();

I had tried start and stop but without render listener. So is it must to get framecount and frames in listener?

I am going to refer your example code.

penfeizhou commented 2 years ago

The render listener‘s timing is precise.

KishorJena commented 2 years ago

The render listener‘s timing is precise.

Is there synchronised way. Because I can't get Frame Bitmap and and Frame info togather. Either I will get frame count in OnStart() or get Bitmaps outside of render listener.

I tried invoking decoder.stop in OnStart like this

... 
OnStart()
  int count = decoder.getFramesCount();
  decoder.stop();
  while(i<count) {
        Bitmap bm = getFrameBitmap(i);
        i++;
  } 
... 

But this is very slow for large number of frames. Takes 1 second for each iteration