您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
75_视频的刻录器
发布时间:2021-03-14 15:17:06编辑:雪饮阅读()
昨天实现了拍照的功能,今天我们再来探索下视频录制的功能。
那么这里布局就简单一个视频录制、停止录制、还有预览区域
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SurfaceView
android:layout_weight="100"
android:id="@+id/sv"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:layout_weight="0"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="开始录制" />
<Button
android:id="@+id/bt_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/bt_start"
android:text="停止录制"
android:enabled="false"
/>
</RelativeLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<SurfaceView
android:layout_weight="100"
android:id="@+id/sv"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<RelativeLayout
android:layout_weight="0"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/bt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="开始录制" />
<Button
android:id="@+id/bt_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/bt_start"
android:text="停止录制"
android:enabled="false"
/>
</RelativeLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
那么接下来就是主程序MainActivity.java:
package com.example.videorecoder;
import androidx.appcompat.app.AppCompatActivity;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button bt_start, bt_stop;
private SurfaceView sv;
private SurfaceHolder holder;
MediaRecorder recorder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//隐藏掉activity的标题栏
// 必须写到setcontentview之前
requestWindowFeature(Window.FEATURE_NO_TITLE);
//实现窗体的全屏显示
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
bt_start = this.findViewById(R.id.bt_start);
bt_stop =this.findViewById(R.id.bt_stop);
bt_start.setOnClickListener(this);
bt_stop.setOnClickListener(this);
sv = this.findViewById(R.id.sv);
holder = sv.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new MySurfaceCallback());
}
private class MySurfaceCallback implements SurfaceHolder.Callback{
public void surfaceCreated(SurfaceHolder holder) {
System.out.println("surface oncreate");
MainActivity.this.holder = holder;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}
public void surfaceDestroyed(SurfaceHolder holder) {System.out.println("surface destroy");}
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_start:
bt_start.setEnabled(false);
bt_stop.setEnabled(true);
recorder = new MediaRecorder();
recorder.reset();
recorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); //从照相机采集视频
recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
recorder.setVideoSize(720, 480);
recorder.setVideoFrameRate(3); //每秒3帧
recorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); //设置视频编码方式
recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
recorder.setOutputFile("/mnt/sdcard/itcast.3gp");
recorder.setPreviewDisplay(holder.getSurface());
try {
recorder.prepare();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//预期准备
recorder.start();//开始刻录
break;
case R.id.bt_stop:
bt_start.setEnabled(true);
bt_stop.setEnabled(false);
if(recorder!=null){
recorder.stop();
recorder.release();
recorder = null;
}
break;
}
}
}
其实主程序中和昨天差不多,具体还就是在录制视频的时候针对真机若有控制台中有日志猫错误日志,或者程序崩溃等,可以结合昨天看到的真机的摄像机参数,进行排除法并对相关参数模糊去查找修正即可。
那么接下来由于录制肯定是要有声音的,再加上摄像权限以及我们要存储到外存上,那么所以清单文件中至少要有这3个权限才行哈。AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.videorecoder">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Videorecoder">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
那么当部署到设备中,勾选了相关权限后如
这里出现了黑屏其实没有什么问题,因为点击开始录制才有预览,我们的逻辑中没有兼容还没有点击开始录制的预览,其实感觉这个影响不大,实际上一开始就预览的那种我个人认为不太友好,一开始我个人认为应该是什么都不显示,当点击开始录制的时候再显示之类的比较好,至于这里黑屏,则可以用其它业务逻辑或者其它方案来美化下即可。
那么当点击开始录制后如
然后录制结束后再点击停止录制
然后就可以看到sdcard中已经产生了对应录制出来的视频文件了
这里有个题外话。
相信大家对H.264都不会陌生,但是你知道H.263吗?
H.263最初设计为基于H.传输系统324。后来发现H.263也可以成功的应用与H.323,H.320,RTSP和SIP。
基于之前的视频编码国际标准,H.263的性能有了革命性的提高。它的第一版于1995年完 成,在所有码率下都优于之前的H.261。 之后还有在1998 年增加了新的功能的第二版H.263+,或者叫H.263v2,以及在2000年完 成的第三版H.263++,即H.263v3。
H.263v2是ITU-T H.263视频编码的第二版标准的非正式名称。 它保持了原先版本H.263的所有信息技术,但是可以通过企业增加了几个附录显著的提高了系统编码工作效率并提供了其它的一些问题能力,例如增强了抵抗传输信道的 数据分析丢失的能力。 H.263项目于1997年底/1998年初完成。
H.263v3:接下来一个被称为“H.263++“ 的项目被随即推出,在H.263+的基础上增加了更多的新的功能。H.263 ++在2000年年底完成。增加了下面的附录:
Appendix A - Inverse transform accuracy specification
Appendix B - hypothetical reference decoder
Annex C- Multiple considerations
Annex d - unrestricted motion vector mode
Appendix E - syntax based arithmetic coding mode
Annex F - Advanced Prediction mode
Annex G - PB-frames mode
Appendix H - forward error correction encoded video signal
在H.263之后,ITU-T的下一代网络视频编解码器是H. 或AVC和MPEG-4第10部分。由于H.264在性能上超越了H.263很多,现在我们通常可以认为H.263是一种过时的标准。大多数新的 视频进行会议通过产品都已经可以支持了H.264视频编解码器,就像过去支持的H263和H.261相同。
话虽然如此,H.263在3GPP中仍然占有很高的地位,后继修订的版本,包 括运营商的标准一直保留着H.263,作为必选的要求,地位远远高于H.264,这是个奇怪的现象。一个重要的可能原因是H.263的编码比H.264的 要轻载,在手机的modem中提供H.263的编解码能力,不提供H.264的编解码能力,或者只提供H.264的解码能力不提供编码能力,如果不是智能 手机不能在主板的其他芯片提供H.264的编解码能力,开发者就没什么办法,H.263可以通过软件来提供,H.264对处理能力的要求很 高,目前需要依赖硬件能力提供。因此H.263仍然需要具有一个很大的市场,尤其对于小尺寸的手持技术设备,屏幕分辨率能力有限,高清无意义。
关键字词:android,h.263,视频录制
上一篇:73_采用照相机拍摄照片