Media Controller in fragments - android

I'm trying to make a media controller in Android studio but using a fragment instead of an activity, I'm using the code below, but it gives me the following error :
public class Tab1Helloworld extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.tab1helloworld, container, false);
return rootView;
VideoView video = (VideoView)rootView.findViewById(R.id.videoView);
video.requestFocus();
String videopath = "android.resource://com.r.teamkape.kiddiecodiel/" + R.raw.helloworldvid;
video.setVideoURI(Uri.parse(videopath));
video.setMediaController(new MediaController(this)); //error in (this)[enter image description here][1]
video.requestFocus();
video.start();
}
}

public class Tab1Helloworld extends Fragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ View rootView = inflater.inflate(R.layout.tab1helloworld,container, false);
VideoView video = (VideoView)rootView.findViewById(R.id.videoView);
video.requestFocus();
String videopath = "android.resource://com.r.teamkape.kiddiecodiel/" + R.raw.helloworldvid;
video.setVideoURI(Uri.parse(videopath));
video.setMediaController(new MediaController(getActivity())); //error in (this)[enter image description here][1]
video.requestFocus();
video.start();
return rootView;
}
}

#xhen, Use below code this works perfect,
in xml layout add this
<sg.xyz.test.util.CustomVideoView
android:id="#+id/videoview"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
/>
in your Fragment class call these medthods
private MediaController mediaController;
private Uri uri;
public void setupVideo(){
if (mediaController == null) {
mediaController = new
MediaController(mContext);
mediaController.setAnchorView(mBinding.videoview);
mBinding.videoview.setMediaController(mediaController);
}
try {
uri = Util.buildURiPath(resourceID);
mBinding.videoview.setVideoURI(uri);
} catch (Exception e) {
Logger.debug("Error: " + e.getMessage());
e.printStackTrace();
}
mBinding.videoview.requestFocus();
mBinding.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mBinding.videoview.start();
mBinding.imageView.setVisibility(View.INVISIBLE);
}
});
mBinding.videoview.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
mp.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
#Override
public void onVideoSizeChanged(MediaPlayer mediaPlayer, int width, int height) {
mediaController.setAnchorView(mBinding.videoview);
}
});
Logger.debug("Duration = " +
mBinding.videoview.getDuration());
}
});
mBinding.videoview.setOnErrorListener(new MediaPlayer.OnErrorListener() {
#Override
public boolean onError(MediaPlayer mp, int what, int extra) {
AlertDialogFactory.buildAlertDialog(mContext, 0, R.string.video_playing_error).show();
return false;
}
});
}
public static Uri buildURiPath(int resourceID)
{
String uriPath = String.valueOf(Uri.parse("android.resource://" + LoginActivity.PACKAGE_NAME + "/"
+resourceID));
Uri uri = Uri.parse(uriPath);
return uri;
}
Replace this mBinding.videoview with your video object that's it.
Now, Create CustomVideoView class
public class CustomVideoView extends VideoView {
private int width;
private int height;
private Context context;
private VideoSizeChangeListener listener;
private boolean isFullscreen;
public CustomVideoView(Context context) {
super(context);
init(context);
}
public CustomVideoView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
/**
* get video screen width and height for calculate size
*
* #param context Context
*/
private void init(Context context) {
this.context = context;
setScreenSize();
}
/**
* calculate real screen size
*/
private void setScreenSize() {
Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= 17) {
//new pleasant way to get real metrics
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
width = realMetrics.widthPixels;
height = realMetrics.heightPixels;
} else if (Build.VERSION.SDK_INT >= 14) {
//reflection for this weird in-between time
try {
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
width = (Integer) mGetRawW.invoke(display);
height = (Integer) mGetRawH.invoke(display);
} catch (Exception e) {
//this may not be 100% accurate, but it's all we've got
width = display.getWidth();
height = display.getHeight();
}
} else {
//This should be close, as lower API devices should not have window navigation bars
width = display.getWidth();
height = display.getHeight();
}
// when landscape w > h, swap it
if (width > height) {
int temp = width;
width = height;
height = temp;
}
}
/**
* set video size change listener
*
*/
public void setVideoSizeChangeListener(VideoSizeChangeListener listener) {
this.listener = listener;
}
public interface VideoSizeChangeListener {
/**
* when landscape
*/
void onFullScreen();
/**
* when portrait
*/
void onNormalSize();
}
#Override
public void setVideoURI(Uri uri) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
retriever.setDataSource(this.getContext(), uri);
width = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
height = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
super.setVideoURI(uri);
super.setVideoURI(uri);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
// full screen when landscape
setSize(height, width);
if (listener != null) listener.onFullScreen();
isFullscreen = true;
} else {
// height = width * 9/16
setSize(width, width * 9 / 16);
if (listener != null) listener.onNormalSize();
isFullscreen = false;
}
}
/**
* #return true: fullscreen
*/
public boolean isFullscreen() {
return isFullscreen;
}
/**
* set video sie
*
* #param w Width
* #param h Height
*/
private void setSize(int w, int h) {
setMeasuredDimension(w, h);
getHolder().setFixedSize(w, h);
}
}

the issue from the error you added
flag Error:(33, 54) error: incompatible types: Tab1Helloworld cannot be converted to Context
is in this line
replace
video.setMediaController(new MediaController(this));
with
video.setMediaController(new MediaController(getActivity()));
also move
return rootView;
to the end of the method after starting the video

Related

Can't enable Flash with the Camera2 Api

I want to enable flash on/off in my camera app, but it isn't working,
Here's the code:
FlashActivity.java
public class FlashActivity extends AppCompatActivity {
private CameraManager mCameraManager;
private String mCameraId;
private Button mTorchOnOffButton;
private Boolean isTorchOn;
private TextureView textureView;
SeekBar sb;
TextToSpeech t1;
private String cameraId;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSessions;
private CaptureRequest.Builder captureRequestBuilder;
private Size imageDimension;
Bitmap src;
private static final int REQUEST_CAMERA_PERMISSION = 200;
private Handler mBackgroundHandler;
private HandlerThread mBackgroundThread;
CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback()
{
#Override
public void onOpened(#NonNull CameraDevice camera) {
cameraDevice = camera;
createCameraPreview();
}
#Override
public void onDisconnected(#NonNull CameraDevice cameraDevice) {
cameraDevice.close();
}
#Override
public void onError(#NonNull CameraDevice cameraDevice, int i) {
cameraDevice.close();
cameraDevice=null;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("FlashActivity", "onCreate()");
setContentView(R.layout.activity_flash);
sb = (SeekBar) findViewById(R.id.seekBar2);
textureView = (TextureView) findViewById(R.id.textureView);
mTorchOnOffButton = (Button) findViewById(R.id.button_on_off);
isTorchOn = false;
textureView.setSurfaceTextureListener(textureListener);
t1 = new TextToSpeech(getApplicationContext(), new TextToSpeech.OnInitListener() {
#Override
public void onInit(int status) {
if (status != TextToSpeech.ERROR) {
t1.setLanguage(Locale.UK);
}
}
});
ToggleButton toggle = (ToggleButton) findViewById(R.id.toggleButton);
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
freeze();
String toSpeak = "Camera Freeze";
Toast.makeText(getApplicationContext(), toSpeak, Toast.LENGTH_SHORT).show();
t1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);
} else {
updatePreview();
String toSpeak = "Back to Live Camera";
Toast.makeText(getApplicationContext(), toSpeak, Toast.LENGTH_SHORT).show();
t1.speak(toSpeak, TextToSpeech.QUEUE_FLUSH, null);
}
}
});
Boolean isFlashAvailable = getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!isFlashAvailable) {
AlertDialog alert = new AlertDialog.Builder(FlashActivity.this)
.create();
alert.setTitle("Error !!");
alert.setMessage("Your device doesn't support flash light!");
alert.setButton(DialogInterface.BUTTON_POSITIVE, "OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// closing the application
finish();
System.exit(0);
}
});
alert.show();
return;
}
mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
mCameraId = mCameraManager.getCameraIdList()[0];
} catch (CameraAccessException e) {
e.printStackTrace();
}
mTorchOnOffButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
if (isTorchOn) {
turnOffFlashLight();
isTorchOn = false;
} else {
turnOnFlashLight();
isTorchOn = true;
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
float scale = ((progress / 10.0f) + 1);
textureView.setScaleX(scale);
textureView.setScaleY(scale);
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
public void turnOnFlashLight() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(mCameraId, true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void turnOffFlashLight() {
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
mCameraManager.setTorchMode(mCameraId, false);
}
} catch (Exception e) {
e.printStackTrace();
}
}
ArrayList rev;
public void freeze() {
Thread td = new Thread(new Runnable() {
public void run() {
Bitmap bmp = textureView.getBitmap();
rev = new ArrayList<Bitmap>();
rev.add(bmp);
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(getApplicationContext(), "" + rev.size(), Toast.LENGTH_LONG).show();
try {
cameraCaptureSessions.stopRepeating();
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
});
}
});
td.start();
}
private void createCameraPreview() {
try {
SurfaceTexture texture = textureView.getSurfaceTexture();
assert texture != null;
texture.setDefaultBufferSize(imageDimension.getWidth(), imageDimension.getHeight());
Surface surface = new Surface(texture);
captureRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(surface);
cameraDevice.createCaptureSession(Arrays.asList(surface), new CameraCaptureSession.StateCallback() {
#Override
public void onConfigured(#NonNull CameraCaptureSession cameraCaptureSession) {
if (cameraDevice == null)
return;
cameraCaptureSessions = cameraCaptureSession;
updatePreview();
}
#Override
public void onConfigureFailed(#NonNull CameraCaptureSession cameraCaptureSession) {
Toast.makeText(FlashActivity.this, "Changed", Toast.LENGTH_SHORT).show();
}
}, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void updatePreview() {
if (cameraDevice == null)
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
try {
cameraCaptureSessions.setRepeatingRequest(captureRequestBuilder.build(), null, mBackgroundHandler);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
private void openCamera() {
CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
try {
cameraId = manager.getCameraIdList()[0];
CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
assert map != null;
imageDimension = map.getOutputSizes(SurfaceTexture.class)[0];
//Check realtime permission if run higher API 23
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.CAMERA,
Manifest.permission.WRITE_EXTERNAL_STORAGE
}, REQUEST_CAMERA_PERMISSION);
return;
}
manager.openCamera(cameraId, stateCallback, null);
} catch (CameraAccessException e) {
e.printStackTrace();
}
}
TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
#Override
public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int i, int i1) {
openCamera();
}
#Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {
}
#Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
return false;
}
#Override
public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {
}
};
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if(requestCode == REQUEST_CAMERA_PERMISSION)
{
if(grantResults[0] != PackageManager.PERMISSION_GRANTED)
{
Toast.makeText(this, "You can't use camera without permission", Toast.LENGTH_SHORT).show();
finish();
}
}
}
#Override
protected void onStop() {
super.onStop();
if(isTorchOn){
turnOffFlashLight();
}
}
#Override
protected void onPause() {
super.onPause();
if(isTorchOn){
turnOffFlashLight();
}
}
#Override
protected void onResume() {
super.onResume();
if(isTorchOn){
turnOnFlashLight();
}
}
}
Here's what I get at LOG
04-03 16:38:34.948 10905-10905/com.example.sumesh.myapplication W/System.err: android.hardware.camera2.CameraAccessException: The camera device is in use already
at android.hardware.camera2.utils.CameraBinderDecorator.throwOnError(CameraBinderDecorator.java:123)
at android.hardware.camera2.utils.CameraBinderDecorator$CameraBinderDecoratorListener.onAfterInvocation(CameraBinderDecorator.java:73)
at android.hardware.camera2.utils.Decorator.invoke(Decorator.java:81)
at java.lang.reflect.Proxy.invoke(Proxy.java:393)
at $Proxy0.setTorchMode(Unknown Source)
at android.hardware.camera2.CameraManager$CameraManagerGlobal.setTorchMode(CameraManager.java:884)
at android.hardware.camera2.CameraManager.setTorchMode(CameraManager.java:501)
at com.example.sumesh.myapplication.FlashActivity.turnOffFlashLight(FlashActivity.java:204)
at com.example.sumesh.myapplication.FlashActivity$5.onClick(FlashActivity.java:150)
at android.view.View.performClick(View.java:5215)
at android.view.View$PerformClick.run(View.java:21196)
}
I have used the linear layout instead of the relativeIlayout, but I
am unable to figure out what thing is exactly posing the error,
all the permissions are already defined in the android manifest,
any suggestions?
Try this , Full code for taking picture using camera2 API , Fragment_Camera4
/**
* A simple {#link Fragment} subclass.
*/
public class Fragment_Camera4 extends Fragment implements
AspectRatioFragment.Listener {
private View view;
private static final String TAG = "MainActivity";
private static final int REQUEST_CAMERA_PERMISSION = 1;
private static final String FRAGMENT_DIALOG = "dialog";
private static final int[] FLASH_OPTIONS = {
CameraView.FLASH_OFF,
CameraView.FLASH_ON,
};
private static final int[] FLASH_ICONS = {
R.drawable.ic_flash_off,
R.drawable.ic_flash_on,
};
private static final int[] FLASH_TITLES = {
R.string.flash_auto,
R.string.flash_off,
R.string.flash_on,
};
private int mCurrentFlash;
private CameraView mCameraView;
private Handler mBackgroundHandler;
private View.OnClickListener mOnClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.take_picture:
if (mCameraView != null) {
mCameraView.takePicture();
}
break;
case R.id.btn_switch_camera:
if (mCameraView != null) {
int facing = mCameraView.getFacing();
mCameraView.setFacing(facing == CameraView.FACING_FRONT ?
CameraView.FACING_BACK : CameraView.FACING_FRONT);
if (facing == CameraView.FACING_FRONT) {
btn_flash_onOff.setVisibility(View.VISIBLE);
} else {
btn_flash_onOff.setVisibility(View.GONE);
}
}
break;
case R.id.btn_flash_onOff:
if (mCameraView != null) {
mCurrentFlash = (mCurrentFlash + 1) % FLASH_OPTIONS.length;
btn_flash_onOff.setImageResource(FLASH_ICONS[mCurrentFlash]);
mCameraView.setFlash(FLASH_OPTIONS[mCurrentFlash]);
}
break;
}
}
};
ImageButton btn_flash_onOff;
public Fragment_Camera4() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_fragment__camera4, container, false);
mCameraView = (CameraView) view.findViewById(R.id.camera);
if (mCameraView != null) {
mCameraView.addCallback(mCallback);
}
ImageButton fab = (ImageButton) view.findViewById(R.id.take_picture);
ImageButton btn_switch_camera = (ImageButton) view.findViewById(R.id.btn_switch_camera);
btn_flash_onOff = (ImageButton) view.findViewById(R.id.btn_flash_onOff);
if (fab != null) {
fab.setOnClickListener(mOnClickListener);
btn_switch_camera.setOnClickListener(mOnClickListener);
btn_flash_onOff.setOnClickListener(mOnClickListener);
}
return view;
}
#Override
public void onResume() {
super.onResume();
mCameraView.start();
}
#Override
public void onPause() {
mCameraView.stop();
super.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
if (mBackgroundHandler != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mBackgroundHandler.getLooper().quitSafely();
} else {
mBackgroundHandler.getLooper().quit();
}
mBackgroundHandler = null;
}
}
#Override
public void onAspectRatioSelected(#NonNull AspectRatio ratio) {
if (mCameraView != null) {
Toast.makeText(getActivity(), ratio.toString(), Toast.LENGTH_SHORT).show();
mCameraView.setAspectRatio(ratio);
}
}
private Handler getBackgroundHandler() {
if (mBackgroundHandler == null) {
HandlerThread thread = new HandlerThread("background");
thread.start();
mBackgroundHandler = new Handler(thread.getLooper());
}
return mBackgroundHandler;
}
private CameraView.Callback mCallback
= new CameraView.Callback() {
#Override
public void onCameraOpened(CameraView cameraView) {
Log.d(TAG, "onCameraOpened");
}
#Override
public void onCameraClosed(CameraView cameraView) {
Log.d(TAG, "onCameraClosed");
}
#Override
public void onPictureTaken(CameraView cameraView, final byte[] data) {
Log.d(TAG, "onPictureTaken " + data.length);
Toast.makeText(cameraView.getContext(), R.string.picture_taken, Toast.LENGTH_SHORT)
.show();
getBackgroundHandler().post(new Runnable() {
#Override
public void run() {
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/_saved_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(myDir, fname);
String final_path = myDir + "/" + fname;
OutputStream os = null;
try {
os = new FileOutputStream(file);
os.write(data);
os.close();
} catch (IOException e) {
Log.w(TAG, "Cannot write to " + file, e);
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// Ignore
}
}
}
Bundle bundle = new Bundle();
bundle.putString("path", final_path);
bundle.putString("type", "picture");
Fragment_Post_Image_Detail post_image_detail = new Fragment_Post_Image_Detail();
post_image_detail.setArguments(bundle);
((BaseActivity) getActivity()).replaceFragmentWithBackstack(post_image_detail);
}
});
}
};
}
Then Cameraview class
import android.content.res.TypedArray;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.os.ParcelableCompat;
import android.support.v4.os.ParcelableCompatCreatorCallbacks;
import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.widget.FrameLayout;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Set;
public class CameraView extends FrameLayout {
/** The camera device faces the opposite direction as the device's screen. */
public static final int FACING_BACK = Constants.FACING_BACK;
/** The camera device faces the same direction as the device's screen. */
public static final int FACING_FRONT = Constants.FACING_FRONT;
/** Direction the camera faces relative to device screen. */
#IntDef({FACING_BACK, FACING_FRONT})
#Retention(RetentionPolicy.SOURCE)
public #interface Facing {
}
/** Flash will not be fired. */
public static final int FLASH_OFF = Constants.FLASH_OFF;
/** Flash will always be fired during snapshot. */
public static final int FLASH_ON = Constants.FLASH_ON;
/** Constant emission of light during preview, auto-focus and snapshot. */
public static final int FLASH_TORCH = Constants.FLASH_TORCH;
/** Flash will be fired automatically when required. */
public static final int FLASH_AUTO = Constants.FLASH_AUTO;
/** Flash will be fired in red-eye reduction mode. */
public static final int FLASH_RED_EYE = Constants.FLASH_RED_EYE;
/** The mode for for the camera device's flash control */
#IntDef({FLASH_OFF, FLASH_ON, FLASH_TORCH, FLASH_AUTO, FLASH_RED_EYE})
public #interface Flash {
}
CameraViewImpl mImpl;
private final CallbackBridge mCallbacks;
private boolean mAdjustViewBounds;
private final DisplayOrientationDetector mDisplayOrientationDetector;
public CameraView(Context context) {
this(context, null);
}
public CameraView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
#SuppressWarnings("WrongConstant")
public CameraView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (isInEditMode()){
mCallbacks = null;
mDisplayOrientationDetector = null;
return;
}
// Internal setup
final PreviewImpl preview = createPreviewImpl(context);
mCallbacks = new CallbackBridge();
if (Build.VERSION.SDK_INT < 21) {
mImpl = new Camera1(mCallbacks, preview);
} else if (Build.VERSION.SDK_INT < 23) {
mImpl = new Camera2(mCallbacks, preview, context);
} else {
mImpl = new Camera2Api23(mCallbacks, preview, context);
}
// Attributes
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CameraView, defStyleAttr,
R.style.Widget_CameraView);
mAdjustViewBounds = a.getBoolean(R.styleable.CameraView_android_adjustViewBounds, false);
setFacing(a.getInt(R.styleable.CameraView_facing, FACING_BACK));
String aspectRatio = a.getString(R.styleable.CameraView_aspectRatio);
if (aspectRatio != null) {
setAspectRatio(AspectRatio.parse(aspectRatio));
} else {
setAspectRatio(Constants.DEFAULT_ASPECT_RATIO);
}
setAutoFocus(a.getBoolean(R.styleable.CameraView_autoFocus, true));
setFlash(a.getInt(R.styleable.CameraView_flash, Constants.FLASH_AUTO));
a.recycle();
// Display orientation detector
mDisplayOrientationDetector = new DisplayOrientationDetector(context) {
#Override
public void onDisplayOrientationChanged(int displayOrientation) {
mImpl.setDisplayOrientation(displayOrientation);
}
};
}
#NonNull
private PreviewImpl createPreviewImpl(Context context) {
PreviewImpl preview;
if (Build.VERSION.SDK_INT < 14) {
preview = new SurfaceViewPreview(context, this);
} else {
preview = new TextureViewPreview(context, this);
}
return preview;
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!isInEditMode()) {
mDisplayOrientationDetector.enable(ViewCompat.getDisplay(this));
}
}
#Override
protected void onDetachedFromWindow() {
if (!isInEditMode()) {
mDisplayOrientationDetector.disable();
}
super.onDetachedFromWindow();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (isInEditMode()){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
// Handle android:adjustViewBounds
if (mAdjustViewBounds) {
if (!isCameraOpened()) {
mCallbacks.reserveRequestLayoutOnOpen();
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
final AspectRatio ratio = getAspectRatio();
assert ratio != null;
int height = (int) (MeasureSpec.getSize(widthMeasureSpec) * ratio.toFloat());
if (heightMode == MeasureSpec.AT_MOST) {
height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec));
}
super.onMeasure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
} else if (widthMode != MeasureSpec.EXACTLY && heightMode == MeasureSpec.EXACTLY) {
final AspectRatio ratio = getAspectRatio();
assert ratio != null;
int width = (int) (MeasureSpec.getSize(heightMeasureSpec) * ratio.toFloat());
if (widthMode == MeasureSpec.AT_MOST) {
width = Math.min(width, MeasureSpec.getSize(widthMeasureSpec));
}
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
heightMeasureSpec);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
// Measure the TextureView
int width = getMeasuredWidth();
int height = getMeasuredHeight();
AspectRatio ratio = getAspectRatio();
if (mDisplayOrientationDetector.getLastKnownDisplayOrientation() % 180 == 0) {
ratio = ratio.inverse();
}
assert ratio != null;
if (height < width * ratio.getY() / ratio.getX()) {
mImpl.getView().measure(
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(width * ratio.getY() / ratio.getX(),
MeasureSpec.EXACTLY));
} else {
mImpl.getView().measure(
MeasureSpec.makeMeasureSpec(height * ratio.getX() / ratio.getY(),
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
}
#Override
protected Parcelable onSaveInstanceState() {
SavedState state = new SavedState(super.onSaveInstanceState());
state.facing = getFacing();
state.ratio = getAspectRatio();
state.autoFocus = getAutoFocus();
state.flash = getFlash();
return state;
}
#Override
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());
setFacing(ss.facing);
setAspectRatio(ss.ratio);
setAutoFocus(ss.autoFocus);
setFlash(ss.flash);
}
/**
* Open a camera device and start showing camera preview. This is typically called from
* {#link Activity#onResume()}.
*/
public void start() {
if (!mImpl.start()) {
//store the state ,and restore this state after fall back o Camera1
Parcelable state=onSaveInstanceState();
// Camera2 uses legacy hardware layer; fall back to Camera1
mImpl = new Camera1(mCallbacks, createPreviewImpl(getContext()));
onRestoreInstanceState(state);
mImpl.start();
}
}
/**
* Stop camera preview and close the device. This is typically called from
* {#link Activity#onPause()}.
*/
public void stop() {
mImpl.stop();
}
/**
* #return {#code true} if the camera is opened.
*/
public boolean isCameraOpened() {
return mImpl.isCameraOpened();
}
/**
* Add a new callback.
*
* #param callback The {#link Callback} to add.
* #see #removeCallback(Callback)
*/
public void addCallback(#NonNull Callback callback) {
mCallbacks.add(callback);
}
/**
* Remove a callback.
*
* #param callback The {#link Callback} to remove.
* #see #addCallback(Callback)
*/
public void removeCallback(#NonNull Callback callback) {
mCallbacks.remove(callback);
}
/**
* #param adjustViewBounds {#code true} if you want the CameraView to adjust its bounds to
* preserve the aspect ratio of camera.
* #see #getAdjustViewBounds()
*/
public void setAdjustViewBounds(boolean adjustViewBounds) {
if (mAdjustViewBounds != adjustViewBounds) {
mAdjustViewBounds = adjustViewBounds;
requestLayout();
}
}
/**
* #return True when this CameraView is adjusting its bounds to preserve the aspect ratio of
* camera.
* #see #setAdjustViewBounds(boolean)
*/
public boolean getAdjustViewBounds() {
return mAdjustViewBounds;
}
/**
* Chooses camera by the direction it faces.
*
* #param facing The camera facing. Must be either {#link #FACING_BACK} or
* {#link #FACING_FRONT}.
*/
public void setFacing(#Facing int facing) {
mImpl.setFacing(facing);
}
/**
* Gets the direction that the current camera faces.
*
* #return The camera facing.
*/
#Facing
public int getFacing() {
//noinspection WrongConstant
return mImpl.getFacing();
}
/**
* Gets all the aspect ratios supported by the current camera.
*/
public Set<AspectRatio> getSupportedAspectRatios() {
return mImpl.getSupportedAspectRatios();
}
/**
* Sets the aspect ratio of camera.
*
* #param ratio The {#link AspectRatio} to be set.
*/
public void setAspectRatio(#NonNull AspectRatio ratio) {
if (mImpl.setAspectRatio(ratio)) {
requestLayout();
}
}
/**
* Gets the current aspect ratio of camera.
*
* #return The current {#link AspectRatio}. Can be {#code null} if no camera is opened yet.
*/
#Nullable
public AspectRatio getAspectRatio() {
return mImpl.getAspectRatio();
}
/**
* Enables or disables the continuous auto-focus mode. When the current camera doesn't support
* auto-focus, calling this method will be ignored.
*
* #param autoFocus {#code true} to enable continuous auto-focus mode. {#code false} to
* disable it.
*/
public void setAutoFocus(boolean autoFocus) {
mImpl.setAutoFocus(autoFocus);
}
/**
* Returns whether the continuous auto-focus mode is enabled.
*
* #return {#code true} if the continuous auto-focus mode is enabled. {#code false} if it is
* disabled, or if it is not supported by the current camera.
*/
public boolean getAutoFocus() {
return mImpl.getAutoFocus();
}
/**
* Sets the flash mode.
*
* #param flash The desired flash mode.
*/
public void setFlash(#Flash int flash) {
mImpl.setFlash(flash);
}
/**
* Gets the current flash mode.
*
* #return The current flash mode.
*/
#Flash
public int getFlash() {
//noinspection WrongConstant
return mImpl.getFlash();
}
/**
* Take a picture. The result will be returned to
* {#link Callback#onPictureTaken(CameraView, byte[])}.
*/
public void takePicture() {
mImpl.takePicture();
}
private class CallbackBridge implements CameraViewImpl.Callback {
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
private boolean mRequestLayoutOnOpen;
CallbackBridge() {
}
public void add(Callback callback) {
mCallbacks.add(callback);
}
public void remove(Callback callback) {
mCallbacks.remove(callback);
}
#Override
public void onCameraOpened() {
if (mRequestLayoutOnOpen) {
mRequestLayoutOnOpen = false;
requestLayout();
}
for (Callback callback : mCallbacks) {
callback.onCameraOpened(CameraView.this);
}
}
#Override
public void onCameraClosed() {
for (Callback callback : mCallbacks) {
callback.onCameraClosed(CameraView.this);
}
}
#Override
public void onPictureTaken(byte[] data) {
for (Callback callback : mCallbacks) {
callback.onPictureTaken(CameraView.this, data);
}
}
public void reserveRequestLayoutOnOpen() {
mRequestLayoutOnOpen = true;
}
}
protected static class SavedState extends BaseSavedState {
#Facing
int facing;
AspectRatio ratio;
boolean autoFocus;
#Flash
int flash;
#SuppressWarnings("WrongConstant")
public SavedState(Parcel source, ClassLoader loader) {
super(source);
facing = source.readInt();
ratio = source.readParcelable(loader);
autoFocus = source.readByte() != 0;
flash = source.readInt();
}
public SavedState(Parcelable superState) {
super(superState);
}
#Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(facing);
out.writeParcelable(ratio, 0);
out.writeByte((byte) (autoFocus ? 1 : 0));
out.writeInt(flash);
}
public static final Parcelable.Creator<SavedState> CREATOR
= ParcelableCompat.newCreator(new ParcelableCompatCreatorCallbacks<SavedState>() {
#Override
public SavedState createFromParcel(Parcel in, ClassLoader loader) {
return new SavedState(in, loader);
}
#Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
});
}
/**
* Callback for monitoring events about {#link CameraView}.
*/
#SuppressWarnings("UnusedParameters")
public abstract static class Callback {
/**
* Called when camera is opened.
*
* #param cameraView The associated {#link CameraView}.
*/
public void onCameraOpened(CameraView cameraView) {
}
/**
* Called when camera is closed.
*
* #param cameraView The associated {#link CameraView}.
*/
public void onCameraClosed(CameraView cameraView) {
}
/**
* Called when a picture is taken.
*
* #param cameraView The associated {#link CameraView}.
* #param data JPEG data.
*/
public void onPictureTaken(CameraView cameraView, byte[] data) {
}
}
}
and xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorgrey">
<com.google.android.cameraview.CameraView
android:id="#+id/camera"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:adjustViewBounds="true"
android:background="#android:color/black" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<ImageButton
android:id="#+id/take_picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="20dp"
android:background="#0000"
app:srcCompat="#drawable/ic_take_pic" />
<ImageButton
android:id="#+id/btn_switch_camera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_margin="20dp"
android:background="#0000"
app:srcCompat="#drawable/ic_reset_camera" />
<ImageButton
android:id="#+id/btn_flash_onOff"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="20dp"
android:background="#0000"
app:srcCompat="#drawable/ic_flash_off" />
</RelativeLayout>
Also DONT FORGET TO ADD RUNTIME PERMISSIONS in OnCreate()

How to play live streaming in RecyclerView using libVLC?

I am developing app to monitor IP camera using my mobile. Below is my MainActivity. I am using libVLC which uses surfaceview to show the video.
public class MainActivity extends AppCompatActivity {
Button prevButton, nextButton;
private int totalPages, currentPage;
RecyclerView recyclerView;
VideoAdapter videoAdapter;
static List<String> cameraList;
Paginator p;
#SuppressLint("AuthLeak")
private String[] vidUrlList = {
"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",
"https://archive.org/download/ksnn_compilation_master_the_internet/ksnn_compilation_master_the_internet_512kb.mp4",
"http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4",
"rtsp://184.72.239.149/vod/mp4:BigBuckBunny_175k.mov",
"http://live.hkstv.hk.lxdns.com/live/hks/playlist.m3u8",
"rtsp://admin:admin#192.0.0.0:200/12"
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
prevButton = (Button) findViewById(R.id.prev_btn);
nextButton = (Button) findViewById(R.id.next_btn);
prevButton.setEnabled(false);
cameraList = new ArrayList<>(Arrays.asList(vidUrlList));
p = new Paginator();
totalPages = Paginator.TOTAL_NUM_ITEMS / Paginator.ITEMS_PER_PAGE;
currentPage = 0;
videoAdapter = new VideoAdapter(this, cameraList);
final RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(3),
true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(new VideoAdapter(MainActivity.this, p.generatePage(currentPage)));
nextButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
currentPage += 1;
recyclerView.setAdapter(new VideoAdapter(MainActivity.this, p.generatePage(currentPage)));
toggleButtons();
}
});
prevButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
currentPage -= 1;
recyclerView.setAdapter(new VideoAdapter(MainActivity.this, p.generatePage(currentPage)));
toggleButtons();
}
});
}
#Override
public void onPause() {
super.onPause();
}
#Override
public void onDestroy() {
super.onDestroy();
}
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
int column = position % spanCount;
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount;
outRect.right = (column + 1) * spacing / spanCount;
if (position < spanCount) {
outRect.top = spacing;
}
outRect.bottom = spacing;
} else {
outRect.left = column * spacing / spanCount;
outRect.right = spacing - (column + 1) * spacing / spanCount;
if (position >= spanCount) {
outRect.top = spacing;
}
}
}
}
private int dpToPx(int dp) {
Resources r = getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dp, r.getDisplayMetrics()));
}
private void toggleButtons() {
if (currentPage == totalPages) {
nextButton.setEnabled(false);
prevButton.setEnabled(true);
} else if (currentPage == 0) {
prevButton.setEnabled(false);
nextButton.setEnabled(true);
} else if (currentPage >= 1 && currentPage <= totalPages) {
nextButton.setEnabled(true);
prevButton.setEnabled(true);
}
}
public static List<String> getModifyList() {
return cameraList;
}}
I used RecylerView and CardView with Paginator option for dispaying 4 cards in each page. Since i have n number of cameras to maintain i used Paginator. Below is my Paginator Class.
public class Paginator {
static List<String> arrNewList = MainActivity.getModifyList();
public static final int TOTAL_NUM_ITEMS = arrNewList.size();
public static final int ITEMS_PER_PAGE = 4;
public static final int ITEMS_REMAINING = TOTAL_NUM_ITEMS % ITEMS_PER_PAGE;
public static final int LAST_PAGE = TOTAL_NUM_ITEMS / ITEMS_PER_PAGE;
public ArrayList<String> generatePage(int currentPage) {
int startItem = currentPage * ITEMS_PER_PAGE;
int numOfData = ITEMS_PER_PAGE;
ArrayList<String> pageData = new ArrayList<>();
if (currentPage == LAST_PAGE && ITEMS_REMAINING > 0) {
for (int i = startItem; i < startItem + ITEMS_REMAINING; i++) {
pageData.add(arrNewList.get(i));
}
} else {
for (int i = startItem; i < startItem + numOfData; i++) {
pageData.add(arrNewList.get(i));
}
}
return pageData;
}}
Here i am trying to set adapter in which video is playing only at the last postion of each page. I dont know how to solve this. I am proving my adapter code below. Here i called SurfaceHolder.Callback and IVideoPlayer interfaces. Do come up with the solution.
public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.ViewHolder>
implements SurfaceHolder.Callback, IVideoPlayer {
Context mContext;
List<String> cameraList;
SurfaceHolder surfaceHolder;
private int mVideoWidth;
private int mVideoHeight;
private final static int VideoSizeChanged = -1;
//private SurfaceView mSurfaceView;
private LibVLC libvlc;
EventHandler mEventHandler;
public VideoAdapter(Context mContext, List<String> cameraList) {
this.mContext = mContext;
this.cameraList = cameraList;
}
#Override
public VideoAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.camera_adapter, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(VideoAdapter.ViewHolder holder, int position) {
surfaceHolder.addCallback(this);
String urlList = cameraList.get(position);
Log.e("List1", "-->" + urlList);
createPlayer(urlList);
}
#Override
public int getItemCount() {
return cameraList.size();
}
public NativeCrashHandler.OnNativeCrashListener nativecrashListener = new NativeCrashHandler.OnNativeCrashListener() {
#Override
public void onNativeCrash() {
Log.e("vlcdebug", "nativecrash");
}
};
#Override
public void surfaceCreated(SurfaceHolder holder) {
Log.e("mylog", "surfaceCreated");
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
try {
if (libvlc != null) {
Log.e("mylog", "libvlc != null");
libvlc.attachSurface(surfaceHolder.getSurface(), this);
} else {
Log.e("mylog", "libvlc == null");
}
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.e("mylog", "surfaceDestroyed");
}
public class ViewHolder extends RecyclerView.ViewHolder {
private SurfaceView mSurfaceView;
public ViewHolder(View itemView) {
super(itemView);
mSurfaceView = itemView.findViewById(R.id.player_surface);
surfaceHolder = mSurfaceView.getHolder();
}
}
private void createPlayer(String vidUrlList) {
//releasePlayer();
try {
libvlc = new LibVLC();
mEventHandler = libvlc.getEventHandler();
libvlc.init(mContext);
libvlc.setHardwareAcceleration(LibVLC.HW_ACCELERATION_FULL);
libvlc.setSubtitlesEncoding("");
libvlc.setAout(LibVLC.AOUT_OPENSLES);
libvlc.setTimeStretching(true);
libvlc.setVerboseMode(true);
libvlc.setNetworkCaching(1000);
NativeCrashHandler.getInstance().setOnNativeCrashListener(
nativecrashListener);
if (LibVlcUtil.isGingerbreadOrLater())
libvlc.setVout(LibVLC.VOUT_ANDROID_WINDOW);
else
libvlc.setVout(LibVLC.VOUT_ANDROID_SURFACE);
LibVLC.restartInstance(mContext);
mEventHandler.addHandler(mHandler);
surfaceHolder.setKeepScreenOn(true);
MediaList list = libvlc.getMediaList();
list.clear();
list.add(new Media(libvlc, LibVLC.PathToURI(vidUrlList)), false);
//list.add(new Media(libvlc, LibVLC.PathToURI(media)), false);
//list.add(new Media(libvlc, LibVLC.PathToURI(media)), false);
libvlc.playIndex(0);
} catch (Exception e) {
Toast.makeText(mContext, "Error creating player!", Toast.LENGTH_SHORT).show();
}
}
private void releasePlayer() {
try {
EventHandler.getInstance().removeHandler(mHandler);
//libvlc.stop();
libvlc.detachSurface();
surfaceHolder = null;
libvlc.closeAout();
libvlc.destroy();
libvlc = null;
mVideoWidth = 0;
mVideoHeight = 0;
} catch (Exception e) {
e.printStackTrace();
}
}
private Handler mHandler = new MyHandler(this);
#Override
public void setSurfaceLayout(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
Message msg = Message.obtain(mHandler, VideoSizeChanged, width,
height);
msg.sendToTarget();
}
#Override
public int configureSurface(Surface surface, int width, int height, int hal) {
Log.d("", "configureSurface: width = " + width + ", height = "
+ height);
if (LibVlcUtil.isICSOrLater() || surface == null)
return -1;
if (width * height == 0)
return 0;
if (hal != 0)
surfaceHolder.setFormat(hal);
surfaceHolder.setFixedSize(width, height);
return 1;
}
#Override
public void eventHardwareAccelerationError() {
//releasePlayer();
Toast.makeText(mContext, "Error with hardware acceleration",
Toast.LENGTH_SHORT).show();
}
#Override
public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) {
}
#SuppressLint("HandlerLeak")
private class MyHandler extends Handler {
private WeakReference<VideoAdapter> mOwner;
MyHandler(VideoAdapter owner) {
mOwner = new WeakReference<>(owner);
}
#Override
public void handleMessage(Message msg) {
try {
VideoAdapter player = mOwner.get();
Log.e("mylog", "handleMessage " + msg.toString());
// Libvlc events
Bundle b = msg.getData();
Log.e("mylog", "handleMessage " + msg.getData());
switch (b.getInt("event")) {
case EventHandler.MediaPlayerEndReached:
Log.e("mylog", "MediaPlayerEndReached");
player.releasePlayer();
break;
case EventHandler.MediaPlayerPlaying:
Log.e("mylog", "MediaPlayerPlaying");
break;
case EventHandler.MediaPlayerPaused:
Log.e("mylog", "MediaPlayerPaused");
break;
case EventHandler.MediaPlayerStopped:
Log.e("mylog", "MediaPlayerStopped");
break;
case EventHandler.MediaPlayerPositionChanged:
Log.i("vlc", "MediaPlayerPositionChanged");
//VideoAdapter.this.notify();
break;
case EventHandler.MediaPlayerEncounteredError:
break;
default:
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}}
The problem is that you get your LibVLC instance using class's member varible like this
// kotlin
private libvlc: LibVLC? = null
...
override fun onBindViewHolder(...) {
libvlc = LibVLC()
...
}
which means each time you call onBindViewHolder, get a new instance of LibVLC and assign it to member variable libvlc, libvlc points to a new address of your new LibVLC instance, and the older one can not be refered again.
In other words, four list items in your RecyclerView share a same LibVLC instance, when you attach view/surface, the later visible views let your libvlc detach views from the older ones the reattach to the newest one, so only the last view can play normally.

How to transform a videoview into a circular shape?

I want to play a video in full screen in a videoview and after some time I want to crop to a circular view?
How can I achieve that ?
There is a better way.
You can create a custom SurfaceView. Which actually clips the view in circular shape. And from this custom view you can set display to MediaPlayer object.
public class VideoSurfaceView extends SurfaceView {
private final static String TAG = "VideoSurfaceView";
private Path clipPath;
private boolean isCircular;
public VideoSurfaceView(Context context) {
super(context);
init();
}
public VideoSurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public VideoSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
clipPath = new Path();
}
#Override
protected void dispatchDraw(Canvas canvas) {
if (this.isCircular)
canvas.clipPath(clipPath);
super.dispatchDraw(canvas);
}
/**
* Crops the view in circular shape
* #param centerX
* #param centerY
* #param radius
*/
public void cropCircle(float centerX, float centerY, int radius) {
Log.i(TAG, "cropCircle: x=" + centerX + " ,y= " + centerY + ", radius=" + radius);
clipPath.addCircle(centerX, centerY, radius, Path.Direction.CW);
}
/**
* Sets the flag for cropping the view in circular shape
* #param isCircular
*/
public void setCircular(boolean isCircular) {
this.isCircular = isCircular;
invalidate();
}
}
In your activity you can implement SurfaceHolder.Callback & set MediaPlayer's display in overridden method.
public class MainActivity extends AppCompatActivity implements MediaPlayer.OnCompletionListener, SurfaceHolder.Callback {
private final static String TAG = "MainActivity";
#BindView(R.id.activity_main_video_surface_view)
protected VideoSurfaceView videoView;
private Handler handler;
private boolean inCircleMode;
private final static int CIRCULAR_INTERVAL = 5000;
private final static int MINIMUM_CARD_HEIGHT = 300;
private final static int MAXIMUM_CARD_HEIGHT = 500;
//Parameters for video view.
private int cropCenterX;
private int cropCenterY;
private int cropRadius;
private int croppedLayoutWidth;
private int croppedLayoutHeight;
private int fullLayoutWidth;
private int fullLayoutHeight;
private MediaPlayer player;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initParameters();
}
/**
* Initialise the parameters used.
*/
private void initParameters() {
SurfaceHolder holder = videoView.getHolder();
holder.addCallback(this);
player = MediaPlayer.create(this, R.raw.bird_s);
player.setOnCompletionListener(this);
//Setting the video with proper aspect ratio.
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
int dimenFull[] = Utility.getVideoDimensions(player, width, height);
fullLayoutWidth = dimenFull[0];
fullLayoutHeight = dimenFull[1];
setVideoLayout();
}
//Runnable for switching the views from circular video to full screen video.
private Runnable runnable = new Runnable() {
#Override
public void run() {
inCircleMode = !inCircleMode;
setVideoLayout();
handler.postDelayed(runnable, CIRCULAR_INTERVAL);
}
};
/**
* Calculates the dimensions required for cropped video view.
*/
private void calculateCroppedParams() {
int dimen[] = Utility.getVideoDimensions(player, 100, 100);
croppedLayoutWidth = dimen[0];
croppedLayoutHeight = dimen[1];
cropRadius = croppedLayoutWidth / 2;
cropCenterX = cropRadius;
cropCenterY = cropRadius;
}
/**
* Change the layout dimensions for video view.
*/
private void setVideoLayout() {
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) videoView.getLayoutParams();
//Changing the margin, width & height of videoView.
layoutParams.setMargins(0, inCircleMode ? cardView.getVideoMargin() : 0, 0, 0);
layoutParams.width = inCircleMode ? croppedLayoutWidth : fullLayoutWidth;
layoutParams.height = inCircleMode ? croppedLayoutHeight : fullLayoutHeight;
layoutParams.addRule(inCircleMode ? RelativeLayout.CENTER_HORIZONTAL : RelativeLayout.CENTER_IN_PARENT);
videoView.cropCircle(cropCenterX, cropCenterY, cropRadius);
videoView.setCircular(inCircleMode);
videoView.setLayoutParams(layoutParams);
}
#Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
#Override
public void onLayout() {
Log.i(TAG, "onLayout: starting runnable");
calculateCroppedParams();
player.start();
}
#Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
player.setDisplay(surfaceHolder);
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
#Override
protected void onStop() {
Log.i(TAG, "onStop");
super.onStop();
}
#Override
protected void onRestart() {
super.onRestart();
}
#Override
protected void onPause() {
super.onPause();
if (player != null && player.isPlaying())
player.pause();
}
#Override
protected void onResume() {
super.onResume();
if (player != null && !player.isPlaying())
player.start();
}
}
For more details on how to crop the video in different shapes, please check my blog post VideoInShapes.
Another way is put this type of image overlay on your videoview Relative or FrameLayout (Circuler is transprent so videoview will visible only in circle)
By default make visibility GONE this imageView and Change VISIBLE it runtime when you want.

How to add media controller on VLC android programatically

I want to to add the media controller on VLC player android integration but i didn't find any option to do that i am sharing the code -
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.otherformat);
load = (ProgressBar) this.findViewById(R.id.load);
intent = getIntent();
load.setVisibility(View.VISIBLE);
handler = new Handler();
mFilePath ="http://mm2.pcslab.com/mm/7h800.mp4";
Log.e(TAG, "Playing: " + mFilePath);
mSurface = (SurfaceView) findViewById(R.id.surface);
holder = mSurface.getHolder();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
setSize(mVideoWidth, mVideoHeight);
}
#Override
protected void onResume() {
super.onResume();
createPlayer(mFilePath);
}
#Override
protected void onPause() {
super.onPause();
releasePlayer();
}
#Override
protected void onDestroy() {
super.onDestroy();
releasePlayer();
}
/**
* Used to set size for SurfaceView
*
* #param width
* #param height
*/
private void setSize(int width, int height) {
mVideoWidth = width;
mVideoHeight = height;
if (mVideoWidth * mVideoHeight <= 1)
return;
if (holder == null || mSurface == null)
return;
int w = getWindow().getDecorView().getWidth();
int h = getWindow().getDecorView().getHeight();
boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
if (w > h && isPortrait || w < h && !isPortrait) {
int i = w;
w = h;
h = i;
}
float videoAR = (float) mVideoWidth / (float) mVideoHeight;
float screenAR = (float) w / (float) h;
if (screenAR < videoAR)
h = (int) (w / videoAR);
else
w = (int) (h * videoAR);
holder.setFixedSize(mVideoWidth, mVideoHeight);
ViewGroup.LayoutParams lp = mSurface.getLayoutParams();
lp.width = w;
lp.height = h;
mSurface.setLayoutParams(lp);
mSurface.invalidate();
}
/**
* Creates MediaPlayer and plays video
*
* #param media
*/
private void createPlayer(String media) {
releasePlayer();
try {
if (media.length() > 0) {
Toast toast = Toast.makeText(this, media, Toast.LENGTH_LONG);
toast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0,
0);
//toast.show();
}
// Create LibVLC
// TODO: make this more robust, and sync with audio demo
ArrayList<String> options = new ArrayList<String>();
//options.add("--subsdec-encoding <encoding>");
options.add("--aout=opensles");
options.add("--audio-time-stretch"); // time stretching
options.add("-vvv"); // verbosity
libvlc = new LibVLC(this, options);
holder.setKeepScreenOn(true);
// Creating media player
mMediaPlayer = new MediaPlayer(libvlc);
mMediaPlayer.setEventListener(mPlayerListener);
mMediaPlayer.setVideoTrackEnabled(true);
// Seting up video output
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.setVideoView(mSurface);
//vout.setSubtitlesView(mSurfaceSubtitles);
vout.addCallback(this);
vout.attachViews();
Media m = new Media(libvlc, Uri.parse(media));
mMediaPlayer.setMedia(m);
mMediaPlayer.play();
////////////////////////////////////////////////
/* //mController = new MediaController(this);
mController = (MediaController)findViewById(R.id.mediaController);
mController.setVisibility(View.VISIBLE);
mController.setAnchorView(mSurface);
mController.show(0);*/
/*mController = new MediaController(this);
mController.setAnchorView(mSurface);
handler.post(new Runnable() {
public void run() {
mController.show();
}
});*/
} catch (Exception e) {
Log.e("Err", e.getMessage()+"");
Toast.makeText(this, "Error in creating player!"+e.getMessage(), Toast
.LENGTH_LONG).show();
}
}
private void releasePlayer() {
if (libvlc == null)
return;
mMediaPlayer.stop();
final IVLCVout vout = mMediaPlayer.getVLCVout();
vout.removeCallback(this);
vout.detachViews();
holder = null;
libvlc.release();
libvlc = null;
mVideoWidth = 0;
mVideoHeight = 0;
}
/**
* Registering callbacks
*/
private MediaPlayer.EventListener mPlayerListener = new MyPlayerListener(this);
#Override
public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen) {
if (width * height == 0)
return;
// store video size
mVideoWidth = width;
mVideoHeight = height;
setSize(mVideoWidth, mVideoHeight);
}
#Override
public void onSurfacesCreated(IVLCVout vout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vout) {
}
#Override
public void onHardwareAccelerationError(IVLCVout vlcVout) {
Log.e(TAG, "Error with hardware acceleration");
this.releasePlayer();
Toast.makeText(this, "Error with hardware acceleration", Toast.LENGTH_LONG).show();
}
private static class MyPlayerListener implements MediaPlayer.EventListener {
private WeakReference<OtherFormat> mOwner;
public MyPlayerListener(OtherFormat owner) {
mOwner = new WeakReference<OtherFormat>(owner);
}
#Override
public void onEvent(MediaPlayer.Event event) {
OtherFormat player = mOwner.get();
switch (event.type) {
case MediaPlayer.Event.EndReached:
Log.d(TAG, "MediaPlayerEndReached");
player.releasePlayer();
break;
case MediaPlayer.Event.Playing:
load.setVisibility(View.GONE);
break;
case MediaPlayer.Event.Paused:
case MediaPlayer.Event.Buffering:
float percent = event.getBuffering(); /* from 0.0f to 100f */
Log.e("Percent><><",""+percent);
break;
case MediaPlayer.Event.Stopped:
default:
break;
}
}
}}
XML for this activity -
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
<ProgressBar
android:id="#+id/load"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="visible"
android:layout_gravity="center"
/>
<MediaController
android:id="#+id/mediaController"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" >
</MediaController>
</FrameLayout>
By this code mediacontrollers not showing please help me how to show media controllers for pause, play and seekbar for video position in surfaceview of vlc media player.
I had the same issue and have found a solution.
Sure, it's too late for answer, but maybe I will save some time to someone.
To add default media control you need to implement it in following way
remove MediaController from layout and add some container for media control to to your activity (it will be added programmatically).
<FrameLayout
android:id="#+id/video_surface_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:foregroundGravity="clip_horizontal|clip_vertical"
tools:ignore="true">
<SurfaceView
android:id="#+id/surface"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center" />
</FrameLayout>
add controller init to onStart activity or to onCreate
import android.widget.MediaController;
private MediaController controller;
#Override
protected void onStart() {
super.onStart();
....
controller = new MediaController(this);
controller.setMediaPlayer(findViewByid(R.id.video_surface_frame));
controller.setAnchorView(mVideoSurfaceFrame);
mVideoSurfaceFrame.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
to define playerInterface, you need to implement the MediaController.MediaPlayerControl interface like this
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mLibVlc.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mLibVlc.getLength();
}
public boolean isPlaying() {
return mLibVlc.isPlaying();
}
public void pause() {
mLibVlc.pause();
}
public void seekTo(int pos) {
mLibVlc.setPosition((float)pos / getDuration());
}
public void start() {
mLibVlc.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
launch your app and tap on video. You will see default media control and it will hide in 10 sec
Good luck!
Link to VideoLan sample on github:
https://code.videolan.org/videolan/vlc-android/blob/f3db2e4a33bf96c03056874322fb5b9304f92259/vlc-android/src/vlc/android/VLC.java
public class Show_Array extends AppCompatActivity implements IVLCVout.Callback {
private TextView container_extension;
private String stream_typee,stream_idd,container_extensionn ;
private String SAMPLE_URL = "";
public int mHeight;
public int mWidth;
private SurfaceView mVideoSurface = null;
private FrameLayout sdk;
private IVLCVout vlcVout;
private LibVLC mLibVlc = null;
private MediaPlayer mMediaPlayer = null;
private int flag = 0;
private ImageButton Resize;
private Media media;
private ArrayList<String> args;
private SurfaceHolder mSurfaceHolderVideo;
private MediaController controller;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.show__array);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//Referances
Resize = findViewById(R.id.Resize);
mVideoSurface = findViewById(R.id.video_surface);
stream_typee = getIntent().getExtras().getString("stream_type");
stream_idd = getIntent().getExtras().getString("stream_id");
container_extensionn = getIntent().getExtras().getString("container_extension");
args = new ArrayList<>();
args.add("-vvv");
mLibVlc = new LibVLC(this, args);
mMediaPlayer = new MediaPlayer(mLibVlc);
vlcVout = mMediaPlayer.getVLCVout();
sdk = findViewById(R.id.sdk);
Resize_video();
setup_url();
controller = new MediaController(this);
controller.setMediaPlayer(playerInterface);
controller.setAnchorView(mVideoSurface);
mVideoSurface.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
controller.show(10000);
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mMediaPlayer.release();
mLibVlc.release();
}
void Resize_video()
{
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
mHeight = displayMetrics.heightPixels;
mWidth = displayMetrics.widthPixels;
Resize.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
flag+=1;
int width = 1000;
int height = 560;
if(flag%2!=0) {
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(width, height);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(width,height);
}
else
{
LinearLayout.LayoutParams myImageLayout = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
myImageLayout.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL;
sdk.setLayoutParams(myImageLayout);
vlcVout.setWindowSize(mWidth,mHeight);
}
}
});
}
void setup_url()
{
//TextView
container_extension = findViewById(R.id.URL);
if (stream_typee.equals("live"))
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+".ts";
container_extension.setText( SAMPLE_URL);
}else
{
SAMPLE_URL = "http://uautv.ru:2095/"+stream_typee+"/webserver/6tE#BzW73#sX/"+stream_idd+"."+container_extensionn;
container_extension.setText( SAMPLE_URL);
}
}
#Override
protected void onStart() {
super.onStart();
vlcVout.setWindowSize(mWidth,mHeight);
vlcVout.setVideoView(mVideoSurface);
vlcVout.attachViews();
mMediaPlayer.getVLCVout().addCallback(this);
if(!SAMPLE_URL.isEmpty()) {
media = new Media(mLibVlc, Uri.parse(SAMPLE_URL));
mMediaPlayer.setMedia(media);
media.release();
mMediaPlayer.play();
}else
{
Toast.makeText(getApplicationContext(),"URL EMPTY",Toast.LENGTH_LONG).show();
}
}
#Override
protected void onStop() {
super.onStop();
mMediaPlayer.stop();
mMediaPlayer.getVLCVout().detachViews();
mMediaPlayer.getVLCVout().removeCallback(this);
}
#TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
#Override
public void onNewLayout(IVLCVout vlcVout, int width, int height, int visibleWidth, int visibleHeight, int sarNum, int sarDen)
{ }
#Override
public void onSurfacesCreated(IVLCVout vlcVout) {
}
#Override
public void onSurfacesDestroyed(IVLCVout vlcVout) {
}
private MediaController.MediaPlayerControl playerInterface = new MediaController.MediaPlayerControl() {
public int getBufferPercentage() {
return 0;
}
public int getCurrentPosition() {
float pos = mMediaPlayer.getPosition();
return (int)(pos * getDuration());
}
public int getDuration() {
return (int)mMediaPlayer.getLength();
}
public boolean isPlaying() {
return mMediaPlayer.isPlaying();
}
public void pause() {
mMediaPlayer.pause();
}
public void seekTo(int pos) {
mMediaPlayer.setPosition((float)pos / getDuration());
}
public void start() {
mMediaPlayer.play();
}
public boolean canPause() {
return true;
}
public boolean canSeekBackward() {
return true;
}
public boolean canSeekForward() {
return true;
}
#Override
public int getAudioSessionId() {
return 0;
}
};
}

How to avoid reinitialization of variable in Live Wallpaper

I have the following Live Wallpaper:
public class GLWallpaperVideoDemo extends GLWallpaperService {
public static final String folder = "video";
public static final String TAG = "GLWVD";
public static String videoName="VIDEOWALL.avi";
//video variables
public int videoWidth,videoHeight;
public boolean videoWideScreen=false;
VideoRenderer renderer = null;
public GLWallpaperVideoDemo() {
super();
Log.e(TAG,"constructor()");
}
#Override
public void onCreate() {
Log.e(TAG,"onCreate()");
super.onCreate();
//transfer video to sdcard
Log.d(TAG,"transferring video asset to sdcard");
copyVideoToCard();
Log.d(TAG,"transferred");
//if videoName == blankVideo, then don't load anything
//TODO
NativeCalls.initVideo();
Log.d(TAG,"Opening video");
NativeCalls.loadVideo("file:/"+"sdcard/"
+GLWallpaperVideoDemo.videoName);
//set video dimensions (now that we opened the video)
videoWidth = NativeCalls.getVideoWidth();
videoHeight = NativeCalls.getVideoHeight();
videoWideScreen = ( videoWidth > videoHeight ) ? true : false;
}
private VideoEngine mEngine=null;
#Override
public Engine onCreateEngine() {
Log.e(TAG,"onCreateEngine()");
mEngine = new VideoEngine();
return mEngine;
}
class VideoEngine extends GLEngine {
VideoEngine() {
super();
Log.e(TAG,"VideoEngine VideoEngine()");
if(renderer==null)renderer = new VideoRenderer(GLWallpaperVideoDemo.this,
this);
setRenderer(renderer);
//setRenderMode(RENDERMODE_WHEN_DIRTY);
setRenderMode(RENDERMODE_CONTINUOUSLY);
}
VideoRenderer getRenderer() { return renderer; }
}
}
And this is the renderer:
public class VideoRenderer implements GLWallpaperService.Renderer {
static private String TAG="Renderer>>>>>>>>>>>>";
static boolean runOnce = false;
//MediaPlayer mediaPlayer = MediaPlayer.create(MyApp.getContext(), R.raw.gunfireusedforboardstage);
//screen variables
int screenWidth=50,screenHeight=50;
int drawWidth, drawHeight; //dimensions of fit-to-screen video
int paddingX, paddingY; //padding for fit-to-screen-video
//texture variables
int powWidth,powHeight;
//pointers
GLWallpaperVideoDemo mParent;
GLWallpaperVideoDemo.VideoEngine mParentEngine;
//lock
static public Object lock = new Object();
//fps
long fpsTime;
public int framecount;
public VideoRenderer() {
super();
Log.e(TAG,"Constructor()");
}
public VideoRenderer(GLWallpaperVideoDemo p,
GLWallpaperVideoDemo.VideoEngine e) {
super();
mParent = p;
mParentEngine = e;
Log.e(TAG,"constructor()");
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Log.e(TAG, "onSurfaceCreated()");
}
void process(int width, int height) {
setScreenDimensions( width, height );
Log.d(TAG,"Killing texture");
NativeCalls.closeOpenGL();
setTextureDimensions( screenWidth, screenHeight );
setFitToScreenDimensions( mParent.videoWidth,
mParent.videoHeight );
if ( !runOnce ) {
Log.e(TAG,"Preparing frame");
NativeCalls.prepareStorageFrame();
}
NativeCalls.initOpenGL();
runOnce = true;
}
//This gets called whenever you preview the wallpaper or set the
//wallpaper
public void onSurfaceChanged(GL10 gl, int width, int height) {
Log.e(TAG,"onSurfaceChanged()");
synchronized(lock) {
process(width, height);
}
}
public void onDrawFrame(GL10 gl) {
synchronized(lock) {
//Log.d(TAG,"Drawing ....");
NativeCalls.getFrame(); // from video
NativeCalls.drawFrame(); // using openGL
if(framecount>300)framecount=0;
framecount++;
//Log.e("framecount",Integer.toString(framecount));
if(framecount==117 || framecount==124 ||framecount==137 ||framecount==145||framecount==159||framecount==167)
{new Thread(new Runnable() {
public void run() {
MediaPlayer mp= MediaPlayer.create(MyApp.getContext(), R.raw.gunfireusedforboardstage);
mp.start();
mp.setOnCompletionListener(new OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
mp.release();
};
});
}
}).start();}
if (MyDebug.showFPS) {
final float fpsRate;
fpsRate = 1000f/((float) (SystemClock.uptimeMillis()
- fpsTime) );
fpsTime = SystemClock.uptimeMillis();
Log.d(TAG,
TAG+"drawFrame(): fps: "
+String.valueOf(fpsRate)
);
}
}
}
Now you see the variable framecount inside the renderer?
It gets reinitialized every time open the settings of the Wallpaper !!!
The result is that the renderer continues its work, but framecount is set again to 0,
the consequence is that the frames are not in sync with the MediaPlayer anymore.
SOLVED:
I made the variable static :-)

Categories

Resources