How to record SurfaceView preview - android

I am working on an app in which I am using Surface View only for preview of frames.
Can anyone tell me how can I record videos of this SurfaceView preview?

You have 3 possibilities :
1 - Capture each frame of your SurfaceView and store all the captured bitmaps into an array, after that you can encode it to a video file using MediaRecord
Here's a full example of how it works : ViewRecorder
2 - Using EZFilter (I've already tested), It's a little long but it's worth a try :
XML :
<RelativeLayout
android:id="#+id/frm"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:animateLayoutChanges="true"
android:gravity="center_vertical|center_horizontal">
<cn.ezandroid.ezfilter.core.environment.TextureFitView
android:id="#+id/render_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_gravity="center"
android:visibility="gone" />
<cn.ezandroid.ezfilter.view.glview.GLLinearLayout
android:id="#+id/gl_layout"
android:layout_width="wrap_content"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#android:color/transparent"
android:visibility="invisible">
<!--PUT YOUR SURFACEVIEW XML HERE-->
</cn.ezandroid.ezfilter.view.glview.GLLinearLayout>
</RelativeLayout>
JAVA :
GLLinearLayout mLinearLayout = findViewById(R.id.gl_layout);
ISupportRecord mSupportRecord;
TextureFitView renderView;
RenderPipeline mRenderPipeline = new RenderPipeline();
mRenderPipeline.setRenderSize((int) surfaceWidth, (int) surfaceHeight);
mRenderPipeline = EZFilter.input(mLinearLayout)
.addFilter(null)
.enableRecord(videoPath, true, false)
.into(renderView);
for (GLRender render : mRenderPipeline.getEndPointRenders()) {
if (render instanceof ISupportRecord) {
mSupportRecord = (ISupportRecord) render;
}
}
mSupportRecord.setRecordSize(surfaceWidth, surfaceHeight);
When you want to start recording :
private void startRecording() {
this.mSupportRecord.startRecording();
this.mSupportRecord.enableRecordAudio(false);
}
To stop recording :
private void stopRecording(){
if (mSupportRecord != null)
mSupportRecord.stopRecording();
}
3 - You can capture the whole screen and crop the recorded video using FFmpeg

Related

How to remove top and bottom black bar from VLCVideoLayout in android

This is my xml .
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="#+id/firstLayout"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/secondView"
android:orientation="vertical">
<FrameLayout
android:id="#+id/videoFrame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.videolan.libvlc.util.VLCVideoLayout
android:id="#+id/videoLayout"
android:fitsSystemWindows="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
<LinearLayout
android:id="#+id/thirdLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/secondView"
android:layout_weight="1"
android:background="#android:color/holo_orange_light"
android:orientation="vertical">
</LinearLayout>
This is my class :
public class WifiActivity extends AppCompatActivity {
private BroadcastReceiver MyReceiver = null;
private static final String url = " rtsp://wowzaec2demo.streamlock.net/vod/mp4:BigBuckBunny_115k.mp4";
private LibVLC libVlc;
private MediaPlayer mediaPlayer;
private VLCVideoLayout videoLayout;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_video);
if (getSupportActionBar() != null) {
getSupportActionBar().hide();
}
libVlc = new LibVLC(this);
mediaPlayer = new MediaPlayer(libVlc);
videoLayout = findViewById(R.id.videoLayout);
}
#Override
protected void onStart() {
super.onStart();
mediaPlayer.attachViews(videoLayout, null, false, false);
Media media = new Media(libVlc, Uri.parse(url));
media.setHWDecoderEnabled(true, false);
media.addOption(":network-caching=600");
mediaPlayer.setMedia(media);
media.release();
mediaPlayer.play();
}
}
after running this code I am able to show live streaming using the given URL look like this.
I am trying to remove the black bar which is showing in the given image I want to keep it full screen please help me how to achieve this I am unable to find any solution for this.
you are setting layout_height="match_parent" for VLCVideoLayout, so currently it behaves properly, according to written code
if you want different height for this view, then you should calculate it and set for VLCVideoLayout. here is fun fact: this class will re-set its width and height at runtime (check out onAttachedToWindow method), so even when you set some fixed values in XML - these will be overwritten. its made for "some reason" by library authors, so let's don't touch this class, but now we know that VLCVideoLayout will always stretch/fit to parent
so now I would create some parent class for this video view only
<LinearLayout
android:id="#+id/firstLayout"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/secondView"
android:orientation="vertical">
<FrameLayout
android:id="#+id/videoFrame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<org.videolan.libvlc.util.VLCVideoLayout
android:id="#+id/videoLayout"
android:fitsSystemWindows="false"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
now as we know that frame/video will match_parent width then we can measure it by measuring screen. if this video would be packed into some more complicated layout, e.g. some small video frame in corner - you should measure size of this area (which oftenly have fixed width/size in such case)
knowing videoFrame width you can calculate easily height with just multiplying by ratio of video
int scrWidth = getScreenWidth();
FrameLayout frameLayout = findViewById(R.id.videoFrame);
double ratio = 16d/9d; // 16:9
frameLayout.getLayoutParams().height = (int)(scrWidth / ratio);

Android : Video not playing in Videoview

I am trying to play video inside a videoview but a blank video view is showing. The video view is inside a popup window. The video is stored in the external directory and I am using setVideoPath to pass the file path.
java code for it:
final View videoPopupView = getLayoutInflater().inflate(R.layout.popup_video_preview, null);
Button cancelVideo = (Button)videoPopupView.findViewById(R.id.cancelVideo);
Button confirmVideo = (Button)videoPopupView.findViewById(R.id.confirmVideo);
final VideoView videoView = (VideoView)videoPopupView.findViewById(R.id.popupVideoView);
final PopupWindow video_popup_window = new PopupWindow(videoPopupView,RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT, true);
if(new File(attachment_Path+attachment_Name).exists())
{
video_popup_window.showAtLocation(videoPopupView, 1, 0, 0);
videoView.setVideoPath(attachment_Path+attachment_Name);
if (mediaController == null) {
mediaController = new android.widget.MediaController(MainActivity.this);
}
videoView.setMediaController(mediaController);
videoView.requestFocus();
videoView.start();
}
And the popup layout looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#80000000">
<VideoView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:id="#+id/popupVideoView"
android:background="#drawable/blackborder"
android:layout_marginTop="25dp"
android:layout_marginBottom="15dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal">
<Button
android:text="Cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="#+id/cancelVideo"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<Button
android:text="Attach"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:id="#+id/confirmVideo"
android:layout_alignParentBottom="true" />
</LinearLayout>
</LinearLayout>
I have referred other solutions and tutorials but everywhere its done like this only. Can someone tell me what is it that I am missing?
EDIT:
This is the file path that is going through :
/storage/emulated/0/Movies/issue_2016_12_30_15_31_13.mp4
EDIT2:Codec Info:
Stream 0
Type: Video
Codec: H264 - MPEG-4 AVC (part 10) (avc1)
Language: English
Resolution: 720x1280
Frame rate: 5.564744
Decoded format: Planar 4:2:0 YUV
Stream 1
Type: Audio
Codec: AMR narrow band (samr)
Language: English
Channels: Mono
Sample rate: 8000 Hz
Bits per sample: 32
You have to go for a custom dialog, add this code -
Dialog mVideoDialog ;
VideoView mVideoFullScreen;
MediaController controller;
Create a method -
mVideoDialog = new Dialog(this);
mVideoDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mVideoDialog.setContentView(R.layout.dialog);
mVideoDialog.setOnKeyListener(this);
mVideoFullScreen = (VideoView) mVideoDialog.findViewById(R.id.videoview1);
controller = new MediaController(this);
showVideo();
}
//Show video method to play the video file -
public void showVideo() {
// TODO Auto-generated method stub
mVideoDialog.show();
mVideoFullScreen.setVideoPath("file:///sdcard/video file name.m4v");
controller.setMediaPlayer(mVideoFullScreen);
mVideoFullScreen.setMediaController(controller);
mVideoFullScreen.requestFocus();
mVideoFullScreen.start();
}
try this code

Move ImageView relatively to another imageView's position- Android Studio

I'm trying to make an ImageView follow another ImageView, by changing it's coordinates. My movement method is that:
public void move(double zx, double zy) {
if (zx < a.getLeft()) {
if (a.getLeft() - zx > 0) {
a.setLeft(a.getLeft() - 1);
} else
a.setLeft(a.getLeft()+1);
}
if (zx > a.getLeft()) {
if (a.getLeft() - zx > 0) {
a.setLeft(a.getLeft() - 1);
} else
a.setLeft(a.getLeft() - 1);
}
if (zy > a.getTop()) {
if (a.getTop() - zy > 0) {
a.setTop(a.getTop() - 1);
} else
a.setTop(a.getTop() + 1);;
}
if (zy < a.getTop()) {
if (a.getTop() - zy > 0) {
a.setTop(a.getTop() - 1);
} else
a.setTop(a.getTop() + 1);
}
}
OnCreate:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fase);
a = (ImageView)findViewById(R.id.a);
b = (ImageView)findViewById(R.id.b);
move(b.getLeft(), b.getTop());
}
"a" and "b" are the ImageViews, and a should follow b. I declared both ImageViews correctly, and the method should work. Instead of it, the ImageView "a" keep in the same position since the application starts. What is wrong? Is the method move declared at the wrong place (onCreate) ? I also have tried to just set the vertical position of "a" in another part of the screen, for testing if it would work. But it didn't (and according to the logCat it's vertical position had changed). The tutorials I found about moving images are based on dragging them, but I haven't still found anything about another kind of movement, like this.
There is my layout (activity_fase.xml) :
<RelativeLayout 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"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="thegame.app.Fase"
android:background="#drawable/seapaint">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/b"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="#drawable/b"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/a"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="#drawable/a"
android:focusable="true"
android:clickable="false"
android:layout_marginBottom="79dp" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/imageView2"
android:layout_above="#+id/b"
android:layout_alignLeft="#+id/a"
android:layout_alignStart="#+id/key"
android:layout_marginBottom="67dp"
android:src="#drawable/key"
android:layout_marginLeft="50dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="Small Text"
android:id="#+id/points"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
I'm new on android developing, and I don't know the difference between relative layout and linear layout.
PROBLEM SOLVED
It's possible to change an ImageView's position for any region of the screen by setting a relativeLayout by code, and adding to it's parameters the leftMargin and the topMargin. Example:
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(80,80);
// 80 is just a number of my choice. There are many possibilities
params.leftMargin = 200;
params.topMargin = 400;
a.setLayoutParams(params);
Now the imageView's coordinates are (200,400). A successive change can be done. If you creat a timer that is called each 0.05 seconds and a task that adds 1 to the leftMargin and topMargin, the image's position will be successfully changed.

Is this possible with the Sneak Peak?

I have gotten the possibility to get my hands on a pair of Google Glasses. Now I am trying to build a simple application with GDK that does the following:
By voice command starts the app (WORKS)
Search in an API for a question (WORKS)
Displays the result in Static cards (WORKS)
Load images from internet on cards (DO NOT WORK)
What does not work, and I am trying to figure out if its possible today is to display the result hits with images that I load from the internet. It seems like it canĀ“t be done right now?
Is there any possibility to add a menu on each of these static cards? to have the possibility to for example navigate to the place in the result.
From what I can see, images can be loaded from the Mirror API, but that is data pushed out to the Google Glasses right? Or are there possibilities for me from inside the GDK to ask the Mirror API for data?
Thank you in advance for your help.
My code where I would like the image to load:
for (int i = 0; i < 10; i++) {
JSONObject advert = adverts.getJSONObject(i);
JSONObject address = advert.getJSONObject("address");
JSONObject companyInfo = advert.getJSONObject("companyInfo");
JSONObject coordinates =
advert.getJSONObject("location").getJSONArray("coordinates").getJSONObject(0);
String companyName = companyInfo.getString("companyName");
String road = address.getString("streetName");
Card card;
card = new Card(activity);
// Here I would like to have images from internet.
card.setText(i+1+". "+companyName);
card.setFootnote("Test");
mCards.add(card);
}
You could replicate the card ui using xml and then use LazyList to load them asynchronously. I've tried it and it works great!
The xml I am using is the following. It may be improved but it works. You'll also probably need to add a TextView for the footer since I didn't use it. You can find the metrics for everything here https://mirror-api-playground.appspot.com/assets/css/base_style.css or by inspecting the playground with firebug or similar https://developers.google.com/glass/tools-downloads/playground
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/llImages"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="360px"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:visibility="gone">
<ImageView
android:id="#+id/ivImage1"
android:layout_width="240px"
android:layout_height="0dp"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:visibility="gone"/>
<LinearLayout
android:id="#+id/llSecondaryImages"
android:orientation="horizontal"
android:layout_width="240px"
android:layout_height="0dp"
android:layout_weight="1"
android:visibility="gone">
<ImageView
android:id="#+id/ivImage2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:visibility="gone"/>
<ImageView
android:id="#+id/ivImage3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:visibility="gone"/>
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/tvMainText"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="34sp"
android:layout_toRightOf="#+id/llImages"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignWithParentIfMissing="true"
android:layout_marginRight="40px"
android:layout_marginTop="10px"
android:layout_marginBottom="40px"
android:layout_marginLeft="30px"
android:maxLines="5"
android:singleLine="false"
android:ellipsize="end"/>
</RelativeLayout>
The only difference is that the main text is not resized depending on its length. I've tried with 3 different libraries but they didn't work as expected, but feel free to improve this if you want. You'll also notice that main text margin-top is set to 10px instead of 40px as playground css. That's because I see some additional margin there when wearing Glass.
Using it from the adapter is like the following. I know it could be improved, but it's just to give you an idea of how to do it ;)
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
View rowView = convertView;
if(rowView == null)
{
LayoutInflater inflater = context.getLayoutInflater();
rowView = inflater.inflate(R.layout.custom_card, null);
CustomRowViewHolder viewHolder = new CustomRowViewHolder();
viewHolder.tvMainText = (TextView) rowView.findViewById(R.id.tvMainText);
viewHolder.ivImage1 = (ImageView) rowView.findViewById(R.id.ivImage1);
viewHolder.ivImage2 = (ImageView) rowView.findViewById(R.id.ivImage2);
viewHolder.ivImage3 = (ImageView) rowView.findViewById(R.id.ivImage3);
viewHolder.llImages = (LinearLayout) rowView.findViewById(R.id.llImages);
viewHolder.llSecondaryImages = (LinearLayout) rowView.findViewById(R.id.llSecondaryImages);
rowView.setTag(viewHolder);
}
CustomClass cc = values.get(position);
CustomRowViewHolder holder = (CustomRowViewHolder) rowView.getTag();
holder.tvMainText.setText(cc.getDescription());
if(!cc.getFiveLastPhotos().isEmpty())
{
holder.llImages.setVisibility(ImageView.VISIBLE);
holder.ivImage1.setVisibility(ImageView.VISIBLE);
ImageLoader.getInstance(context.getApplicationContext()).DisplayImage(cc.getFiveLastPhotos().get(0).getSrcPhoto(), holder.ivImage1, null, ImageLoader.NO_ANIMATION);
if(cc.getFiveLastPhotos().size()>1)
{
holder.llSecondaryImages.setVisibility(ImageView.VISIBLE);
holder.ivImage2.setVisibility(ImageView.VISIBLE);
ImageLoader.getInstance(context.getApplicationContext()).DisplayImage(cc.getFiveLastPhotos().get(1).getSrcPhoto(), holder.ivImage2, null, ImageLoader.NO_ANIMATION);
if(cc.getFiveLastPhotos().size()>2)
{
holder.ivImage3.setVisibility(ImageView.VISIBLE);
ImageLoader.getInstance(context.getApplicationContext()).DisplayImage(cc.getFiveLastPhotos().get(2).getSrcPhoto(), holder.ivImage3, null, ImageLoader.NO_ANIMATION);
}
else
{
holder.ivImage3.setVisibility(ImageView.GONE);
}
}
else
{
holder.ivImage2.setVisibility(ImageView.GONE);
holder.ivImage3.setVisibility(ImageView.GONE);
holder.llSecondaryImages.setVisibility(ImageView.GONE);
}
}
else
{
holder.llImages.setVisibility(ImageView.GONE);
holder.ivImage1.setVisibility(ImageView.GONE);
holder.ivImage2.setVisibility(ImageView.GONE);
holder.ivImage3.setVisibility(ImageView.GONE);
holder.llSecondaryImages.setVisibility(ImageView.GONE);
}
return rowView;
}
I hope it helps you, and please post any suggestion you may have

Message while starting Camera preview on SurfaceView on Android

Let me begin with the coding first.
My xml file (relevant part of it) contains this:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ffffff">
<SurfaceView
android:id="#+id/cameraView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:visibility="gone" />
<LinearLayout
android:id="#+id/layStatus"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:id="#+id/txtStatus"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#90000000"
android:paddingBottom="5dip"
android:paddingTop="5dip"
android:gravity="center_vertical|center_horizontal"
android:textSize="20dip" />
</LinearLayout>
</FrameLayout>
As you can see I've got a basic set up, a frame layout which contains a surfaceview (which has visibility set to gone) and another layout with a simple TextView.
Here is what I have in my activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout);
cameraView = (SurfaceView)findViewById(R.id.cameraView);
surfaceHolder = cameraView.getHolder();
surfaceHolder.addCallback(CompassActivity.this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void btnCameraOnClick(View target) {
cameraView.setVisibility(View.VISIBLE);
}
Starting the camera preview is done in Surface changed, which fires when visibility of the surface changes.
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
txtStatus.setVisibility(View.Visible);
txtStatus.setText("Starting camera");
camera = Camera.open();
if (camera != null){
try {
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
List<Size> sizes = parameters.getSupportedPreviewSizes();
Size size = sizes.get(0);
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.setPreviewDisplay(holder);
camera.startPreview();
txtStatis.setVisibility(View.GONE);
} catch (IOException e) {
}
}
}
So what's the problem ? I want to simply display a text while the camera preview starts. To do this, I make the txtStatus visible and set a text to it. When the preview is started, I simply hide it. Well, it doesn't work like this, When I press a button to start camera preview, the UI thread freezes waiting for the preview and my status message is not displayed. How can I fix it ? There is a solution at HERE but I was thinking that maybe there is a simpler one.
Thank you for your time.
Camera start up takes some time - external process shall be started and everything set up. I would speculate, that surface changed callback is executed directly from setVisibility() and blocks UI thread. Solution is pretty simple - just spawn new thread and do camera init there.
In my OCR applicatios I start camera in onResume() - since I always need working preview
You may find my OCR android demos helpful:
http://sourceforge.net/projects/javaocr/
( camera preview, with overlays )

Categories

Resources