-
Notifications
You must be signed in to change notification settings - Fork 209
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #212 from ksvc/v4.3.1-13346
update to v4.3.1-13346
- Loading branch information
Showing
16 changed files
with
749 additions
and
28 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
210 changes: 210 additions & 0 deletions
210
demo/src/com/ksyun/media/streamer/demo/AnimatedImageCapture.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
package com.ksyun.media.streamer.demo; | ||
|
||
import android.content.Context; | ||
import android.graphics.Bitmap; | ||
import android.graphics.Canvas; | ||
import android.graphics.Color; | ||
import android.graphics.Rect; | ||
import android.net.Uri; | ||
import android.util.Log; | ||
|
||
import com.facebook.common.executors.CallerThreadExecutor; | ||
import com.facebook.common.references.CloseableReference; | ||
import com.facebook.datasource.BaseDataSubscriber; | ||
import com.facebook.datasource.DataSource; | ||
import com.facebook.datasource.DataSubscriber; | ||
import com.facebook.drawee.backends.pipeline.Fresco; | ||
import com.facebook.imagepipeline.animated.base.AnimatedDrawableFrameInfo; | ||
import com.facebook.imagepipeline.animated.base.AnimatedImage; | ||
import com.facebook.imagepipeline.animated.base.AnimatedImageFrame; | ||
import com.facebook.imagepipeline.core.ImagePipeline; | ||
import com.facebook.imagepipeline.image.CloseableAnimatedImage; | ||
import com.facebook.imagepipeline.image.CloseableBitmap; | ||
import com.facebook.imagepipeline.image.CloseableImage; | ||
import com.facebook.imagepipeline.request.ImageRequest; | ||
import com.facebook.imagepipeline.request.ImageRequestBuilder; | ||
import com.ksyun.media.streamer.capture.ImgTexSrcPin; | ||
import com.ksyun.media.streamer.framework.ImgTexFrame; | ||
import com.ksyun.media.streamer.framework.SrcPin; | ||
import com.ksyun.media.streamer.util.gles.GLRender; | ||
|
||
import java.util.Date; | ||
import java.util.Timer; | ||
import java.util.TimerTask; | ||
|
||
/** | ||
* Class to decode animated GIF/WEBP. | ||
*/ | ||
|
||
public class AnimatedImageCapture { | ||
private static final String TAG = "AnimatedImageCapture"; | ||
private static final boolean VERBOSE = false; | ||
|
||
private int mIndex; | ||
private Date mLastDate; | ||
private int mRepeatCount; // TODO: handle gif/webp repeat count | ||
private Bitmap mBitmap; | ||
private Canvas mCanvas; | ||
private Bitmap mTempBitmap; | ||
private Timer mTimer; | ||
private CloseableReference<? extends CloseableImage> mCloseableReference; | ||
|
||
private ImgTexSrcPin mImgTexSrcPin; | ||
|
||
public AnimatedImageCapture(GLRender glRender) { | ||
mImgTexSrcPin = new ImgTexSrcPin(glRender); | ||
} | ||
|
||
public SrcPin<ImgTexFrame> getSrcPin() { | ||
return mImgTexSrcPin; | ||
} | ||
|
||
public void start(Context context, String url) { | ||
if (url == null) { | ||
return; | ||
} | ||
|
||
Uri uri = Uri.parse(assets2Asset(url)); | ||
ImagePipeline imagePipeline = Fresco.getImagePipeline(); | ||
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri).build(); | ||
DataSource<CloseableReference<CloseableImage>> dataSource = | ||
imagePipeline.fetchDecodedImage(request, context); | ||
dataSource.subscribe(mDataSubscriber, CallerThreadExecutor.getInstance()); | ||
} | ||
|
||
private String assets2Asset(String url) { | ||
if (url.startsWith("assets://")) { | ||
url = url.replaceFirst("assets://", "asset:///"); | ||
} | ||
return url; | ||
} | ||
|
||
public void stop() { | ||
if (mTimer != null) { | ||
mTimer.cancel(); | ||
mTimer = null; | ||
} | ||
if (mCloseableReference != null) { | ||
CloseableReference.closeSafely(mCloseableReference); | ||
mCloseableReference = null; | ||
} | ||
mImgTexSrcPin.updateFrame(null, false); | ||
} | ||
|
||
private void updateFrame() { | ||
if (mCloseableReference == null) { | ||
return; | ||
} | ||
try { | ||
CloseableImage closeableImage = mCloseableReference.get(); | ||
if (closeableImage instanceof CloseableBitmap) { | ||
Bitmap bitmap = ((CloseableBitmap) closeableImage).getUnderlyingBitmap(); | ||
if (bitmap != null && !bitmap.isRecycled()) { | ||
mBitmap = Bitmap.createBitmap(bitmap); | ||
mImgTexSrcPin.updateFrame(mBitmap, false); | ||
} | ||
return; | ||
} | ||
|
||
if (!(closeableImage instanceof CloseableAnimatedImage)) { | ||
return; | ||
} | ||
AnimatedImage animatedImage = ((CloseableAnimatedImage) closeableImage).getImage(); | ||
int w = animatedImage.getWidth(); | ||
int h = animatedImage.getHeight(); | ||
if (mBitmap == null || mBitmap.isRecycled()) { | ||
Log.d(TAG, "Got animated image " + w + "x" + h); | ||
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); | ||
mTempBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); | ||
mCanvas = new Canvas(mBitmap); | ||
} | ||
if (mIndex >= animatedImage.getFrameCount()) { | ||
mRepeatCount++; | ||
mIndex = 0; | ||
int loopCount = animatedImage.getLoopCount(); | ||
if (loopCount > 0 && mRepeatCount >= loopCount) { | ||
Log.d(TAG, "repeat ended, repeat times: " + mRepeatCount); | ||
return; | ||
} | ||
} | ||
|
||
AnimatedImageFrame imageFrame = animatedImage.getFrame(mIndex); | ||
int duration = imageFrame.getDurationMs(); | ||
AnimatedDrawableFrameInfo frameInfo = animatedImage.getFrameInfo(mIndex); | ||
imageFrame.renderFrame(frameInfo.width, frameInfo.height, mTempBitmap); | ||
if (VERBOSE) { | ||
Log.d(TAG, "blend: " + frameInfo.blendOperation.name() + | ||
" dispose: " + frameInfo.disposalMethod.name() + | ||
" x=" + frameInfo.xOffset + " y=" + frameInfo.yOffset + | ||
" " + frameInfo.width + "x" + frameInfo.height); | ||
} | ||
if (frameInfo.blendOperation == AnimatedDrawableFrameInfo.BlendOperation.NO_BLEND) { | ||
mBitmap.eraseColor(Color.TRANSPARENT); | ||
} | ||
Rect srcRect = new Rect(0, 0, frameInfo.width, frameInfo.height); | ||
Rect dstRect = new Rect(frameInfo.xOffset, frameInfo.yOffset, | ||
frameInfo.xOffset + frameInfo.width, frameInfo.yOffset + frameInfo.height); | ||
mCanvas.drawBitmap(mTempBitmap, srcRect, dstRect, null); | ||
if (VERBOSE) { | ||
Log.d(TAG, "frame " + mIndex + " got, duration=" + duration); | ||
} | ||
mImgTexSrcPin.updateFrame(mBitmap, false); | ||
imageFrame.dispose(); | ||
|
||
mIndex++; | ||
if (mLastDate == null) { | ||
mLastDate = new Date(); | ||
} | ||
mLastDate = new Date(mLastDate.getTime() + duration); | ||
mTimer.schedule(new TimerTask() { | ||
@Override | ||
public void run() { | ||
updateFrame(); | ||
} | ||
}, mLastDate); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
|
||
private DataSubscriber mDataSubscriber = | ||
new BaseDataSubscriber<CloseableReference<? extends CloseableImage>>() { | ||
|
||
@Override | ||
public void onNewResultImpl( | ||
DataSource<CloseableReference<? extends CloseableImage>> dataSource) { | ||
if (!dataSource.isFinished()) { | ||
return; | ||
} | ||
|
||
// get ref | ||
mCloseableReference = dataSource.getResult(); | ||
|
||
// reset | ||
mIndex = 0; | ||
mRepeatCount = 0; | ||
mLastDate = null; | ||
mBitmap = null; | ||
mTempBitmap = null; | ||
mCanvas = null; | ||
|
||
// create timer | ||
mTimer = new Timer("AnimatedImage"); | ||
mTimer.schedule(new TimerTask() { | ||
@Override | ||
public void run() { | ||
updateFrame(); | ||
} | ||
}, 0); | ||
} | ||
|
||
@Override | ||
public void onFailureImpl(DataSource dataSource) { | ||
Throwable throwable = dataSource.getFailureCause(); | ||
// handle failure | ||
if (throwable != null) { | ||
throwable.printStackTrace(); | ||
} | ||
} | ||
}; | ||
} |
Oops, something went wrong.