如何使用ffmpeg usb摄像头进行摄像头录像

?您当前的位置: >
[FFmpeg]FFmpeg实现监控摄像头的RTSP协议转RTMP协议直播
时间: 19:04</.cn
[FFmpeg]FFmpeg实现监控摄像头的RTSP协议转RTMP协议直播,我们使用的摄像头是海康的可以通过rtsp协议获取到摄像头的直播数据。所以可以通过
整理了一下要解决如下问题:
1、& 摄像头的数据采集。
2、& 如何将采集到的数据交给Red5处理。
& 解决方法:
1、& 我们使用的摄像头是海康的可以通过rtsp协议获取到摄像头的直播数据。所以可以通过 :
2、& rtsp://admin:8.1.77:554/h264/ch1/main/av_stream
3、& 实现视频数据的采集。
获取到数据流后如何利用Red5发布出去呢?
5、& 因为获取到的数据是rtsp协议的,所以要转协议成rtmp,ffmpeg可以实现这个功能。
具体步骤:
1、& 首先要安装流媒体服务器Red5用于rtmp数据的接收与发布。
l&&&&&&&& 下载Red5
l&&&&&&&& 我下载的版本是setup-Red5-1.0.1-java6.exe
l&&&&&&&& 安装Red5&
l&&&&&&&& 在安装的过程会弹窗要求设置一些服务器信息。
l&&&&&&&& 设置服务器的IP
设置HTTP访问端口
&后面一直&next&即可。
&安装完成后访问: 如果可以看到
&Red5默认是会安装成系统的服务的,如果重复启动会报端口占用的错误。
在http://localhost:5080/installer/ 页面中安装Red5自带的Demo OflaDemo。安装好后访问http://localhost:5080/oflaDemo/index.html 即可已看到通过rtmp 点播的视频文件视频。这样你的Red5服务器就安装完成了。
下载安装FFmpeg, 安装 ffmpeg教程:
这里下载的是编译好的, 直接解压好,并将bin目录加入到path环境变量下即可。&&&&&&
l&&&&&&&& 运行Red5
l&&&&&&&& 在命令行下执行:
ffmpeg -i &rtsp://admin:8.1.77:554/h264/ch1/main/av_stream& -f flv -r 25 -s 640x480 -an &rtmp://localhost/oflaDemo/hello&
l&&&&&&&& 修改Red5安装目录下的 webapps\oflaDemo\index.html 文件,将jwplayer的 file 属性改成 &hello&。
l&&&&&&&& 访问 http://localhost:5080/oflaDemo/index.html 在你所修改的播放器上是否可以看到摄像头的直播了。
酷播交流2群:(新群)
酷播交流1群:(已满)本帖子已过去太久远了,不再提供回复功能。Powered byAndroid采集摄像头数据,通过ffmpeg推送流至服务器Android采集摄像头数据,通过ffmpeg推送流,通过AdobeMediaServer查看,为什么播放视频总是隔一段时间一缓冲,而且播放
Android 采集摄像头数据 , 通过ffmpeg推送流至服务器
Android 采集摄像头数据 , 通过ffmpeg推送流, 通过AdobeMediaServer查看 , 为什么播放视频总是隔一段时间一缓冲 , 而且播放有延迟。求大神帮忙啊
AVFormatContext *ofmt_
AVStream* video_
//视音频流对应的结构体,用于视音频编解码。
AVCodecContext* pCodecC
AVCodec* pC
AVPacket enc_ // 存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
AVFrame *pFrameYUV; // 存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)
int framecnt = 0;
int64_t start_
//const char* out_path = "rtmp://192.168.2.176/live/livestream";
//Output FFmpeg&#039;s av_log()
void custom_log(void *ptr, int level, const char* fmt, va_list vl) {
FILE *fp = fopen("/storage/emulated/0/av_log.txt", "a+");
vfprintf(fp, fmt, vl);
fflush(fp);
fclose(fp);
JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_initial(JNIEnv *env,
jobject obj, jint width, jint height) {
const char* out_path = "rtmp://192.168.2.176/live/livestream";
yuv_width =
yuv_height =
y_length = width *
uv_length = width * height / 4;
//FFmpeg av_log() callback
av_log_set_callback(custom_log);
av_register_all();
avformat_network_init();
//output initialize
avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", out_path);
//output encoder initialize
//函数的参数是一个解码器的ID,返回查找到的解码器(没有找到就返回NULL)。
pCodec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!pCodec) {
LOGE("Can not find encoder!n");
return -1;
pCodecCtx = avcodec_alloc_context3(pCodec);
pCodecCtx-&pix_fmt = PIX_FMT_YUV420P;
pCodecCtx-&width =
pCodecCtx-&height =
pCodecCtx-&time_base.num = 1;
pCodecCtx-&time_base.den = 25;
pCodecCtx-&bit_rate = 400000;
pCodecCtx-&gop_size = 250;
/* Some formats want stream headers to be separate. */
if (ofmt_ctx-&oformat-&flags & AVFMT_GLOBALHEADER)
pCodecCtx-&flags |= CODEC_FLAG_GLOBAL_HEADER;
//H264 codec param
//pCodecCtx-&me_range = 16;
//pCodecCtx-&max_qdiff = 4;
//pCodecCtx-&qcompress = 0.6;
pCodecCtx-&qmin = 10;
pCodecCtx-&qmax = 51;
//Optional Param
pCodecCtx-&max_b_frames = 1;
// Set H264 preset and tune
AVDictionary *param = 0;
av_dict_set(&param, "preset", "ultrafast", 0);
av_dict_set(&param, "tune", "zerolatency", 0);
av_opt_set(pCodecCtx-&priv_data, "preset", "superfast", 0);
av_opt_set(pCodecCtx-&priv_data, "tune", "zerolatency", 0);
//打开编码器
if (avcodec_open2(pCodecCtx, pCodec, &param) & 0) {
LOGE("Failed to open encoder!n");
return -1;
//Add a new stream to output,should be called by the user before avformat_write_header() for muxing
video_st = avformat_new_stream(ofmt_ctx, pCodec);
if (video_st == NULL) {
return -1;
video_st-&time_base.num = 1;
video_st-&time_base.den = 25;
video_st-&codec = pCodecC
//Open output URL,set before avformat_write_header() for muxing
if (avio_open(&ofmt_ctx-&pb, out_path, AVIO_FLAG_READ_WRITE) & 0) {
LOGE("Failed to open output file!n");
return -1;
//Write File Header
avformat_write_header(ofmt_ctx, NULL);
start_time = av_gettime();
JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_encode(JNIEnv *env,
jobject obj, jbyteArray yuv) {
int enc_got_frame = 0;
int i = 0;
// 为解码帧分配内存
pFrameYUV = avcodec_alloc_frame();
uint8_t *out_buffer = (uint8_t *) av_malloc(
avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx-&width,
pCodecCtx-&height));
avpicture_fill((AVPicture *) pFrameYUV, out_buffer, PIX_FMT_YUV420P,
pCodecCtx-&width, pCodecCtx-&height);
//安卓摄像头数据为NV21格式,此处将其转换为YUV420P格式
jbyte* in = (jbyte*) (*env)-&GetByteArrayElements(env, yuv, 0);
memcpy(pFrameYUV-&data[0], in, y_length);
for (i = 0; i & uv_ i++) {
*(pFrameYUV-&data[2] + i) = *(in + y_length + i * 2);
*(pFrameYUV-&data[1] + i) = *(in + y_length + i * 2 + 1);
pFrameYUV-&format = AV_PIX_FMT_YUV420P;
pFrameYUV-&width = yuv_
pFrameYUV-&height = yuv_
enc_pkt.data = NULL;
enc_pkt.size = 0;
// 定义AVPacket对象后,请使用av_init_packet进行初始化
av_init_packet(&enc_pkt);
/** 编码一帧视频数据
* int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt,
const AVFrame *frame, int *got_packet_ptr);
该函数每个参数的含义在注释里面已经写的很清楚了,在这里用中文简述一下:
avctx:编码器的AVCodecContext。
avpkt:编码输出的AVPacket。
frame:编码输入的AVFrame。
got_packet_ptr:成功编码一个AVPacket的时候设置为1。
函数返回0代表编码成功。
ret = avcodec_encode_video2(pCodecCtx, &enc_pkt, pFrameYUV, &enc_got_frame);
av_frame_free(&pFrameYUV);
if (enc_got_frame == 1) {
LOGI("Succeed to encode frame: %5dtsize:%5dn", framecnt,
enc_pkt.size);
framecnt++;
//标识该AVPacket所属的视频/音频流。
enc_pkt.stream_index = video_st-& //标识该视频/音频流
//Write PTS
AVRational time_base = ofmt_ctx-&streams[0]-&time_ //{ 1, 1000 };
AVRational r_framerate1 = { 60, 2 };
//{ 50, 2 };
AVRational time_base_q = { 1, AV_TIME_BASE };
//Duration between 2 frames (us)
int64_t calc_duration = (double) (AV_TIME_BASE)
* (1 / av_q2d(r_framerate1));
//内部时间戳
//Parameters
//enc_pkt.pts = (double)(framecnt*calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base));
enc_pkt.pts = av_rescale_q(framecnt * calc_duration, time_base_q,
time_base);
enc_pkt.dts = enc_pkt.
enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base); //(double)(calc_duration)*(double)(av_q2d(time_base_q)) / (double)(av_q2d(time_base));
enc_pkt.pos = -1;
int64_t pts_time = av_rescale_q(enc_pkt.dts, time_base, time_base_q);
int64_t now_time = av_gettime() - start_
if (pts_time & now_time)
av_usleep(pts_time - now_time);
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
av_free_packet(&enc_pkt);
output(ofmt_ctx);
JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_flush(JNIEnv *env,
jobject obj) {
AVPacket enc_
if (!(ofmt_ctx-&streams[0]-&codec-&codec-&capabilities & CODEC_CAP_DELAY))
while (1) {
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2(ofmt_ctx-&streams[0]-&codec, &enc_pkt, NULL,
&got_frame);
if (ret & 0)
if (!got_frame) {
LOGI("Flush Encoder: Succeed to encode 1 frame!tsize:%5dn",
enc_pkt.size);
//Write PTS
AVRational time_base = ofmt_ctx-&streams[0]-&time_ //{ 1, 1000 };
AVRational r_framerate1 = { 60, 2 };
AVRational time_base_q = { 1, AV_TIME_BASE };
//Duration between 2 frames (us)
int64_t calc_duration = (double) (AV_TIME_BASE)
* (1 / av_q2d(r_framerate1));
//内部时间戳
//Parameters
enc_pkt.pts = av_rescale_q(framecnt * calc_duration, time_base_q,
time_base);
enc_pkt.dts = enc_pkt.
enc_pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base);
//转换PTS/DTS(Convert PTS/DTS)
enc_pkt.pos = -1;
framecnt++;
ofmt_ctx-&duration = enc_pkt.duration *
/* mux encoded frame */
ret = av_interleaved_write_frame(ofmt_ctx, &enc_pkt);
if (ret & 0)
//Write file trailer
av_write_trailer(ofmt_ctx);
JNIEXPORT jint JNICALL Java_com_zhanghui_test_MainActivity_close(JNIEnv *env,
jobject obj) {
if (video_st)
avcodec_close(video_st-&codec);
avio_close(ofmt_ctx-&pb);
avformat_free_context(ofmt_ctx);
java 代码:
package com.zhanghui.
import java.io.IOE
import java.util.A
import com.xqh.util.AppL
import android.annotation.TargetA
import android.app.A
import android.content.pm.PackageM
import android.hardware.C
import android.os.AsyncT
import android.os.B
import android.os.B
import android.os.E
import android.util.L
import android.view.M
import android.view.MenuI
import android.view.SurfaceH
import android.view.SurfaceV
import android.view.V
import android.view.View.OnClickL
import android.widget.B
import android.widget.T
@SuppressWarnings("deprecation")
public class MainActivity extends Activity {
private static final String TAG = "MainActivity";
private Button mTakeB
private Button mPlayB
private Camera mC
private SurfaceView mSurfaceV
private SurfaceHolder mSurfaceH
private boolean isRecording =
private int i = 0;
private class StreamTask extends AsyncTask&Void, Void, Void& {
private byte[] mD
// 构造函数
StreamTask(byte[] data) {
this.mData =
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
if (mData != null) {
Log.i("&&&" , Arrays.toString(mData));
encode(mData);
private StreamTask mStreamT
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Camera.PreviewCallback mPreviewCallbacx = new Camera.PreviewCallback() {
public void onPreviewFrame(byte[] arg0, Camera arg1) {
// TODO Auto-generated method stub
if (null != mStreamTask) {
switch (mStreamTask.getStatus()) {
case RUNNING:
case PENDING:
mStreamTask.cancel(false);
if(arg0 != null ){
for (int i = 0; i & arg0. i++) {
Log.e("&&&", arg0[i]+"");
util.e("&&", Arrays.toString(arg0));
encode(arg0);
mStreamTask = new StreamTask(arg0);
mStreamTask.execute((Void) null);
mTakeButton = (Button) findViewById(R.id.take_button);
mPlayButton = (Button) findViewById(R.id.play_button);
PackageManager pm = this.getPackageManager();
boolean hasCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)
|| pm.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT)
|| Build.VERSION.SDK_INT & Build.VERSION_CODES.GINGERBREAD;
if (!hasCamera)
mTakeButton.setEnabled(false);
mTakeButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
if (mCamera != null) {
if (isRecording) {
mTakeButton.setText("Start");
mCamera.setPreviewCallback(null);
Toast.makeText(MainActivity.this, "encode done",
Toast.LENGTH_SHORT).show();
isRecording =
mTakeButton.setText("Stop");
initial(mCamera.getParameters().getPreviewSize().width,
mCamera.getParameters().getPreviewSize().height);
stream("rtmp://192.168.2.176/live/livestream");
mCamera.setPreviewCallback(mPreviewCallbacx);
isRecording =
mPlayButton.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
String folderurl = Environment.getExternalStorageDirectory()
.getPath();
String inputurl = folderurl + "/" + "aa.flv";
// stream("rtmp://192.168.2.176/live/livestream");
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
SurfaceHolder holder = mSurfaceView.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
if (mCamera != null) {
mCamera.stopPreview();
mSurfaceView =
mSurfaceHolder =
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
if (mCamera != null) {
mCamera.setPreviewDisplay(arg0);
mSurfaceHolder = arg0;
} catch (IOException exception) {
Log.e(TAG, "Error setting up preview display", exception);
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
if (mCamera == null)
Camera.Parameters parameters = mCamera.getParameters();
parameters.setPreviewSize(640, 480);
parameters.setPictureSize(640, 480);
mCamera.setParameters(parameters);
mCamera.startPreview();
mSurfaceHolder = arg0;
} catch (Exception e) {
Log.e(TAG, "could not start preview", e);
mCamera.release();
@TargetApi(9)
protected void onResume() {
super.onResume();
if (Build.VERSION.SDK_INT &= Build.VERSION_CODES.GINGERBREAD) {
mCamera = Camera.open(0);
mCamera = Camera.open();
protected void onPause() {
super.onPause();
if (mCamera != null) {
mCamera.release();
public native int initial(int width, int height);
public native int encode(byte[] yuvimage);
public native int flush();
public native int close();
public native int stream(String outputurl);
System.loadLibrary("avutil-54");
System.loadLibrary("swresample-1");
System.loadLibrary("avcodec-56");
System.loadLibrary("avformat-56");
System.loadLibrary("swscale-3");
System.loadLibrary("postproc-53");
System.loadLibrary("avfilter-5");
System.loadLibrary("avdevice-56");
System.loadLibrary("encode");
【云栖快讯】支撑千亿营收,阿里如何做研发?淘宝如何做敏捷实践?如何面对开发中的“黑天鹅”事件?6月29日首届阿里研发效能嘉年华,独家直播,赶紧预约吧!&&
为您提供简单高效、处理能力可弹性伸缩的计算服务,帮助您快速构建更稳定、安全的应用,提升运维效率,降低 IT 成本...
RDS是一种稳定可靠、可弹性伸缩的在线数据库服务。支持MySQL、SQL Server、PostgreSQL、高...

我要回帖

更多关于 使用电脑摄像头录像 的文章

 

随机推荐