加入 摄像头采集和264编码,再使用live555直播

1、摄像头采集和264编码

将x264改成编码一帧的接口,码流不写入文件而是直接写入内存中(int  Encode_frame 函数中)。

/*
* Filename: encodeapp.h
* Auther: mlj
* Create date: 2013/ 1/20
*/
#ifndef _ENCODEAPP_H_
#define _ENCODEAPP_H_ #include "x264.h"
#include <stdint.h>
#define WRITEOUT_RECONSTRUCTION 1 typedef int32_t INT32;
typedef signed char INT8; typedef struct _EncodeApp
{
x264_t *h;
x264_picture_t pic;
x264_param_t param; void *outBufs;//一帧码流的缓存
int outBufslength;//总大小
int bitslen;//实际码流大小 FILE *bits; // point to output bitstream file
#ifdef WRITEOUT_RECONSTRUCTION
FILE *p_rec ;
#endif
}EncodeApp;
INT32 EncoderInit(EncodeApp* EncApp,INT8 *config_filename);
INT32 EncoderEncodeFrame(EncodeApp* EncApp);
INT32 EncoderDestroy(EncodeApp* EncApp); #endif
 /*
* Filename: encodeapp.c
* Auther: mlj
* Create date: 2013/ 1/20
*/
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include "..\inc\encodeapp.h" #pragma comment(lib,"libx264.lib") extern int Encode_frame(EncodeApp* EncApp, x264_t *h, x264_picture_t *pic );
INT32 EncoderEncodeFrame(EncodeApp* EncApp)
{
//printf("processing frame %d...",j);
int i;
//int i_frame, i_frame_total;
int64_t i_file=0; /* Encode frames */
//EncApp->pic.i_pts = (int64_t)i_frame * (&EncApp->param)->i_fps_den;
{
/* Do not force any parameters */
EncApp->pic.i_type = X264_TYPE_AUTO;
EncApp->pic.i_qpplus1 = 0;
} i_file += Encode_frame(EncApp, EncApp->h, &EncApp->pic ); //fwrite(EncApp,EncApp->bits); #ifdef WRITEOUT_RECONSTRUCTION
//write reconstruction
#endif
return 0;
} INT32 EncoderDestroy(EncodeApp* EncApp)
{ x264_picture_clean( &EncApp->pic );
x264_encoder_close( EncApp->h ); if(EncApp->outBufs )
free(EncApp->outBufs ); fclose(EncApp->bits);
#ifdef WRITEOUT_RECONSTRUCTION
fclose(EncApp->p_rec);
#endif
return 0;
}
//x264.c中改写
int Encode_frame(EncodeApp* EncApp, x264_t *h, x264_picture_t *pic )
{
x264_picture_t pic_out;
x264_nal_t *nal;
int i_nal, i;
int i_file = 0; if( x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out ) < 0 )
{
fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" );
}
EncApp->bitslen = 0;
for( i = 0; i < i_nal; i++ )
{
int i_size; if( mux_buffer_size < nal[i].i_payload * 3/2 + 4 )
{
mux_buffer_size = nal[i].i_payload * 2 + 4;
x264_free( mux_buffer );
mux_buffer = x264_malloc( mux_buffer_size );
} i_size = mux_buffer_size;
x264_nal_encode( mux_buffer, &i_size, 1, &nal[i] );
//i_file += p_write_nalu( EncApp->bits, mux_buffer, i_size );
if( EncApp->outBufslength < ( EncApp->bitslen+i_size) )
{
void* temp= malloc( EncApp->bitslen+i_size);
memcpy((unsigned char*)temp, (unsigned char*)(EncApp->outBufs), EncApp->bitslen);
free(EncApp->outBufs);
EncApp->outBufs = temp;
}
memcpy( (unsigned char*)(EncApp->outBufs)+ EncApp->bitslen,mux_buffer, i_size);
EncApp->bitslen += i_size;
}
//p_write_nalu( EncApp->bits, (unsigned char*)EncApp->outBufs, EncApp->bitslen );
//if (i_nal)
// p_set_eop( EncApp->bits, &pic_out ); return i_file;
} INT32 EncoderInit(EncodeApp* EncApp,INT8 *config_filename)
{
int argc; cli_opt_t opt;
static char *para[] =
{
"",
"-q",
"28",
"-o",
"test.264",
"G:\\sequence\\walk_vga.yuv",
"640x480",
"--no-asm"
};
char **argv = para;;
//para[0] = argv[0];
//argv = para;
argc = sizeof(para)/sizeof(char*);
x264_param_default( &EncApp->param );
/* Parse command line */
if( Parse( argc, argv, &EncApp->param, &opt ) < 0 )
return -1;
//param->i_frame_total = 100;
// EncApp->param.i_width = 640;
// EncApp->param.i_height = 480;
//EncApp->param.rc.i_qp_constant = 28; if( ( EncApp->h = x264_encoder_open( &EncApp->param ) ) == NULL )
{
fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
return -1;
} /* Create a new pic */
x264_picture_alloc( &EncApp->pic, X264_CSP_I420, EncApp->param.i_width, EncApp->param.i_height ); EncApp->outBufs = malloc(1024*1024);
EncApp->outBufslength = 1024*1024;
EncApp->bits =0 ;
#ifdef WRITEOUT_RECONSTRUCTION
EncApp->p_rec = NULL;
#endif
EncApp->bits = fopen("test_vc.264","wb"); #ifdef WRITEOUT_RECONSTRUCTION
EncApp->p_rec = fopen("test_rec_vc.yuv", "wb");
#endif if(0==EncApp->bits)
{
printf("Can't open output files!\n");
return -1;
} return 0;
}

摄像头采集和264编码 源代码:http://download.csdn.NET/user/mlj318

结果速度不是很快,640x480 采集加编码只能达到10fps.

相关配置:需要OpenCV库和libx264.lib.

包含目录 G:\workspace\video4windows\CameraDS and 264\inc;H:\TDDOWNLOAD\OPEN_CV\opencv\build\include\opencv2;H:\TDDOWNLOAD\OPEN_CV\opencv\build\include\opencv;H:\TDDOWNLOAD\OPEN_CV\opencv\build\include;

库目录 G:\workspace\video4windows\CameraDS and code\lib;H:\TDDOWNLOAD\OPEN_CV\opencv\build\x86\vc10\lib;

链接器 附加库目录 G:\workspace\video4windows\CameraDS and 264\lib;

链接器 附加依赖项

opencv_calib3d243d.lib

opencv_contrib243d.lib

opencv_core243d.lib

opencv_features2d243d.lib

opencv_flann243d.lib

opencv_gpu243d.lib

opencv_haartraining_engined.lib

opencv_highgui243d.lib

opencv_imgproc243d.lib

opencv_legacy243d.lib

opencv_ml243d.lib

opencv_nonfree243d.lib

opencv_objdetect243d.lib

opencv_photo243d.lib

opencv_stitching243d.lib

opencv_ts243d.lib

opencv_video243d.lib

opencv_videostab243d.lib

libx264.lib

2、再加入live555直播

class Cameras
{
public:
void Init();
void GetNextFrame();
void Destory();
public:
CCameraDS camera1;
CCameraDS camera2;
EncodeApp encodeapp;
IplImage *pFrame1 ;
IplImage *pFrame2 ;
unsigned char *RGB1;
unsigned char *RGB2;
unsigned char *YUV1;
unsigned char *YUV2;
unsigned char *YUV_merge;
}; void Cameras::Init()
{
// 1、考虑到已经存在了显示图像的窗口,那就不必再次驱动摄像头了,即便往下驱动那也是摄像头已被占用。
if(IsWindowVisible(FindWindow(NULL, g_szTitle)))
{
exit (-1);
} //仅仅获取摄像头数目
int m_iCamCount = CCameraDS::CameraCount();
printf("There are %d cameras.\n", m_iCamCount); if(m_iCamCount==0)
{
fprintf(stderr, "No cameras.\n");
exit( -1);
} //打开第一个摄像头
if(! camera1.OpenCamera(0, false, WIDTH,HEIGHT)) //不弹出属性选择窗口,用代码制定图像宽和高
{
fprintf(stderr, "Can not open camera1.\n");
exit( -1);
}
if(! camera2.OpenCamera(1, false, WIDTH,HEIGHT)) //不弹出属性选择窗口,用代码制定图像宽和高
{
fprintf(stderr, "Can not open camera2.\n");
exit( -1);
}
cvNamedWindow("camera1");
cvNamedWindow("camera2"); EncoderInit(&encodeapp,NULL); pFrame1 = camera1.QueryFrame();
pFrame2 = camera2.QueryFrame(); RGB1=(unsigned char *)malloc(pFrame1->height*pFrame1->width*3);
YUV1=(unsigned char *)malloc(pFrame1->height*pFrame1->width*1.5);
RGB2=(unsigned char *)malloc(pFrame2->height*pFrame2->width*3);
YUV2=(unsigned char *)malloc(pFrame2->height*pFrame2->width*1.5);
YUV_merge=(unsigned char *)malloc(pFrame2->height*pFrame2->width*1.5);
}
void Cameras::GetNextFrame()
{
{
pFrame1 = camera1.QueryFrame();
pFrame2 = camera2.QueryFrame();
cvShowImage("camera1", pFrame1);
cvShowImage("camera2", pFrame2);
for(int i=0;i<pFrame1->height;i++)
{
for(int j=0;j<pFrame1->width;j++)
{
RGB1[(i*pFrame1->width+j)*3] = pFrame1->imageData[i * pFrame1->widthStep + j * 3 + 2];;
RGB1[(i*pFrame1->width+j)*3+1]= pFrame1->imageData[i * pFrame1->widthStep + j * 3 + 1];
RGB1[(i*pFrame1->width+j)*3+2] = pFrame1->imageData[i * pFrame1->widthStep + j * 3 ]; RGB2[(i*pFrame1->width+j)*3] = pFrame2->imageData[i * pFrame1->widthStep + j * 3 + 2];;
RGB2[(i*pFrame1->width+j)*3+1]= pFrame2->imageData[i * pFrame1->widthStep + j * 3 + 1];
RGB2[(i*pFrame1->width+j)*3+2] = pFrame2->imageData[i * pFrame1->widthStep + j * 3 ];
}
} Convert(RGB1, YUV1,pFrame1->width,pFrame1->height);
Convert(RGB2, YUV2,pFrame2->width,pFrame2->height);
mergeleftrigth(YUV_merge,YUV1,YUV2,pFrame2->width,pFrame2->height); unsigned char *p1,*p2;
p1=YUV_merge;
p2=encodeapp.pic.img.plane[0];//
for(int i=0;i<pFrame1->height;i++)
{
memcpy(p2,p1,pFrame1->width);
p1+=pFrame1->width;
p2+=WIDTH;
}
p2=encodeapp.pic.img.plane[1];
for(int i=0;i<pFrame1->height/2;i++)
{
memcpy(p2,p1,pFrame1->width/2);
p1+=pFrame1->width/2;
p2+=WIDTH/2;
}
p2=encodeapp.pic.img.plane[2];
for(int i=0;i<pFrame1->height/2;i++)
{
memcpy(p2,p1,pFrame1->width/2);
p1+=pFrame1->width/2;
p2+=WIDTH/2;
}
EncoderEncodeFrame(&encodeapp);
}
}
void Cameras::Destory()
{ free(RGB1);
free(RGB2);
free(YUV1);
free(YUV2);
free(YUV_merge);
camera1.CloseCamera();
camera2.CloseCamera();
cvDestroyWindow("camera1");
cvDestroyWindow("camera2");
EncoderDestroy(&encodeapp);
}
void H264FramedLiveSource::doGetNextFrame()
{ //if( filesize(fp) > fMaxSize)
// fFrameSize = fread(fTo,1,fMaxSize,fp);
//else
//{
// fFrameSize = fread(fTo,1,filesize(fp),fp);
// fseek(fp, 0, SEEK_SET);
//}
//fFrameSize = fMaxSize; TwoWayCamera.GetNextFrame();
fFrameSize = TwoWayCamera.encodeapp.bitslen;
if( fFrameSize > fMaxSize)
{
fNumTruncatedBytes = fFrameSize - fMaxSize;
fFrameSize = fMaxSize;
}
else
{
fNumTruncatedBytes = 0;
} memmove(fTo, TwoWayCamera.encodeapp.outBufs, fFrameSize); nextTask() = envir().taskScheduler().scheduleDelayedTask( 0,
(TaskFunc*)FramedSource::afterGetting, this);//表示延迟0秒后再执行 afterGetting 函数
return;
}

源代码:http://download.csdn.net/user/mlj318

640x480  只能达到3.5fps.

相关配置:需要opencv库和libx264.lib.

包含目录 H:\TDDOWNLOAD\OPEN_CV\opencv\build\include\opencv2;H:\TDDOWNLOAD\OPEN_CV\opencv\build\include\opencv;H:\TDDOWNLOAD\OPEN_CV\opencv\build\include;G:\workspace\avs\live555test -send\live555test\inc;G:\workspace\avs\live555test\live555test\BasicUsageEnvironment\include;G:\workspace\avs\live555test\live555test\UsageEnvironment\include;G:\workspace\avs\live555test\live555test\liveMedia\include;G:\workspace\avs\live555test\live555test\groupsock\include;

库目录 G:\workspace\avs\live555test\live555test\lib;H:\TDDOWNLOAD\OPEN_CV\opencv\build\x86\vc10\lib;

链接器 附加库目录 G:\workspace\video4windows\CameraDS and 264\lib;

链接器 附加依赖项

opencv_calib3d243d.lib

opencv_contrib243d.lib

opencv_core243d.lib

opencv_features2d243d.lib

opencv_flann243d.lib

opencv_gpu243d.lib

opencv_haartraining_engined.lib

opencv_highgui243d.lib

opencv_imgproc243d.lib

opencv_legacy243d.lib

opencv_ml243d.lib

opencv_nonfree243d.lib

opencv_objdetect243d.lib

opencv_photo243d.lib

opencv_stitching243d.lib

opencv_ts243d.lib

opencv_video243d.lib

opencv_videostab243d.lib

libx264.lib

出现的错误:

1>LIBCMTD.lib(sprintf.obj) : error LNK2005: _sprintf 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义

1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: _exit 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义

1>LIBCMTD.lib(crt0dat.obj) : error LNK2005: __exit 已经在 MSVCRTD.lib(MSVCR100D.dll) 中定义

LIBCMTD.lib与 MSVCRTD.lib 冲突,在链接器- 输入 -忽略特定默认库中加上 LIBCMTD.lib 即可。


FROM: http://www.cnblogs.com/mlj318/archive/2013/01/25/2873143.html

【视频开发】【Live555】摄像头采集,264编码,live555直播的更多相关文章

  1. 【视频开发】RTSP SERVER(基于live555)详细设计

    /* *本文基于LIVE555的嵌入式的RTSP流媒体服务器一个设计文档,个中细节现剖于此,有需者可参考指正,同时也方便后期自己查阅.(本版本是基于2011年的live555) 作者:llf_17@q ...

  2. ffmpeg摄像头采集h264编码RTP发送

    一. 相关API说明 1. av_register_all 2. avformat_network_init 不管是流媒体发送还是流媒体接收, 需要先执行该函数. 3. avformat_alloc_ ...

  3. Android IOS WebRTC 音视频开发总结(七六)-- 探讨直播低延迟低流量的粉丝连麦技术

    本文主要探讨基于WebRTC的P2P直播粉丝连麦技术 (作者:郝飞,亲加云CTO,编辑:dora),最早发表在[这里] 支持原创,转载必须注明出处,欢迎关注微信公众号blacker(微信ID:blac ...

  4. WebRTC 音视频开发

    WebRTC 音视频开发 webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译 ...

  5. 转:Android IOS WebRTC 音视频开发总结 (系列文章集合)

    随笔分类 - webrtc   Android IOS WebRTC 音视频开发总结(七八)-- 为什么WebRTC端到端监控很关键? 摘要: 本文主要介绍WebRTC端到端监控(我们翻译和整理的,译 ...

  6. (转)C++实现RTMP协议发送H.264编码及AAC编码的音视频,摄像头直播

    转:http://www.cnblogs.com/haibindev/archive/2011/12/29/2305712.html C++实现RTMP协议发送H.264编码及AAC编码的音视频 RT ...

  7. 【秒懂音视频开发】23_H.264编码

    本文主要介绍一种非常流行的视频编码:H.264. 计算一下:10秒钟1080p(1920x1080).30fps的YUV420P原始视频,需要占用多大的存储空间? (10 * 30) * (1920 ...

  8. Android IOS WebRTC 音视频开发总结(八十五)-- 使用WebRTC广播网络摄像头视频(下)

    本文主要介绍WebRTC (我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacker(微信ID:bl ...

  9. C++实现RTMP协议发送H.264编码及AAC编码的音视频

    http://www.cnblogs.com/haibindev/archive/2011/12/29/2305712.html C++实现RTMP协议发送H.264编码及AAC编码的音视频 RTMP ...

随机推荐

  1. 如何有效使用Project(1)——编制进度计划、保存基准

    1.前言: 软件产品的研发.升级.定制等,一般都是以项目的形式进行,此时项目进度计划以及资源使用情况就变成了项目经理关注的重点.如何让项目计划有效可控,及时暴露问题?如何查看资源的负荷情况,看资源分配 ...

  2. 如何使用project制定项目计划?(附详细步骤截图)

    使用project制定项目计划可以分为六个步骤,如下图(1): 图(1)-project制定项目计划步骤 下面我们就以project2010为例,按上图所示步骤对如何制定项目计划进行详细说明: 一.创 ...

  3. wordpress模板加载顺序汇总

    我们要创建一个新的wordpress模板需要先了解有哪些页面模板,这些页面模板的文件是什么?它们是怎么工作的?下面ytkah汇总了一些常用的wordpress模板结构方便大家查找 首页 首先WordP ...

  4. StringTokenizer字符串分解器

    示例: StringTokenizer st = new StringTokenizer(key, ",", false); while (st.hasMoreTokens()) ...

  5. ora-00054资源正忙,但指定以nowait方式

    select l.session_id,o.owner,o.object_name from v$locked_object l,dba_objects o where l.object_id=o.o ...

  6. php 常用操作数组函数

    我们有很多操作数组的元素,我们这一节先讲一些.在6.3里面我们会总结更多的数组常用函数.深圳dd马达 下面的几个主要是移动数组指针和压入弹出数组元素的和个函数. 函数 功能 array_shift 弹 ...

  7. something about 乘法逆元

    before 在求解除法取模问题(a / b) % m时,我们可以转化为(a % (b * m)) / b, 但是如果b很大,则会出现爆精度问题,所以我们避免使用除法直接计算. (逆元就像是倒数一样的 ...

  8. 【03NOIP普及组】麦森数(信息学奥赛一本通 1925)(洛谷 1045)

    [题目描述] 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它 ...

  9. Java 堆栈内存的理解

    Java中变量在内存中的分配1). 类变量(static修饰的变量):在程序加载时系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便高速访问.静态变量的生命周期—一直持续到整个“系统”关闭 2). ...

  10. D3.js的v5版本入门教程(第五章)—— 选择、插入、删除元素

    D3.js的v5版本入门教程(第五章) 1.选择元素 现在我们已经知道,d3.js中选择元素的函数有select()和selectAll(),下面来详细讲解一下 假设我们的<body>中有 ...