Live555 直播源 以及MediaSubsession
/*
* H264DeviceSource.hh
*
* Created on: 2014年7月19日
* Author: zjzhang
*/ #ifndef H264DEVICESOURCE_HH_
#define H264DEVICESOURCE_HH_
#include<DeviceSource.hh> class H264DeviceSource: public DeviceSource {
public:
static DeviceSource* createNew(UsageEnvironment& env,u_int8_t index=1,u_int width=352,u_int height=288,u_int fps=15,u_int kbps=100);
protected:
H264DeviceSource(UsageEnvironment& env,u_int8_t index,u_int width,u_int height,u_int fps,u_int kbps);
virtual ~H264DeviceSource();
private:
virtual void doGetNextFrame();
virtual unsigned maxFrameSize() const;
int fHeight;
int fWidth;
void *fH264Encoder;
u_int8_t * fBuffer;
u_int fBufferSize;
}; #endif /* H264DEVICESOURCE_HH_ */
/*
* H264DeviceSource.cpp
*
* Created on: 2014年7月19日
* Author: zjzhang
*/ #include "H264DeviceSource.hh"
#ifdef __cplusplus
extern "C" {
#endif
#include "H264Stream.h"
#ifdef __cplusplus
}
#endif
DeviceSource*
H264DeviceSource::createNew(UsageEnvironment& env, u_int8_t index, u_int width,
u_int height, u_int fps, u_int kbps) {
return new H264DeviceSource(env, index, width, height, fps, kbps);
} H264DeviceSource::H264DeviceSource(UsageEnvironment& env, u_int8_t index,
u_int width, u_int height, u_int fps, u_int kbps) :
DeviceSource(env, DeviceParameters()) {
openCamera(1);
getFrame(1);
fHeight = getHeight(1);
fWidth = getWidth(1);
openH264Encoder(fWidth, fHeight, fps, kbps, &fH264Encoder);
fBufferSize = fHeight * fWidth * 3 / 2;
fBuffer = new uint8_t[fBufferSize]; } H264DeviceSource::~H264DeviceSource() {
// TODO Auto-generated destructor stub delete[] fBuffer;
closeH264Encoder(fH264Encoder);
closeCamera(1);
}
unsigned H264DeviceSource::maxFrameSize() const {
// By default, this source has no maximum frame size.
return 4096;
}
void H264DeviceSource::doGetNextFrame() {
if (!isCurrentlyAwaitingData())
return; // we're not ready for the data yet unsigned char * rgbBuffer = getFrame(1);
ConvertRGB2YUV(fWidth, fHeight, rgbBuffer, fBuffer);
int newFrameSize = encodeFrame(fH264Encoder, fBuffer, fBufferSize); // Deliver the data here:
if (newFrameSize < 0) {
handleClosure();
return;
}
if (newFrameSize > fMaxSize) {
fFrameSize = fMaxSize;
fNumTruncatedBytes = newFrameSize - fMaxSize;
} else {
fFrameSize = newFrameSize;
}
if (fFrameSize > 0) {
int result = 0;
int p = 0;
do {
unsigned long len = 0;
result = getNextPacket(fH264Encoder, fBuffer + p, &len);
p += len;
} while (result > 0);
} gettimeofday(&fPresentationTime, NULL); // If you have a more accurate time - e.g., from an encoder - then use that instead.
// If the device is *not* a 'live source' (e.g., it comes instead from a file or buffer), then set "fDurationInMicroseconds" here.
memmove(fTo, fBuffer, fFrameSize); FramedSource::afterGetting(this);
}
#ifndef _DEVIC_SERVER_MEDIA_SUBSESSION_HH
#define _DEVICE_SERVER_MEDIA_SUBSESSION_HH #ifndef _ON_DEMAND_SERVER_MEDIA_SUBSESSION_HH
#include "OnDemandServerMediaSubsession.hh"
#endif
class DeviceSource;
class DeviceServerMediaSubsession: public OnDemandServerMediaSubsession {
public:
static DeviceServerMediaSubsession*
createNew(UsageEnvironment& env,
Boolean reuseFirstSource); // Used to implement "getAuxSDPLine()":
void checkForAuxSDPLine1();
void afterPlayingDummy1();
protected: // we're a virtual base class
DeviceServerMediaSubsession(UsageEnvironment& env,
Boolean reuseFirstSource);
virtual ~DeviceServerMediaSubsession(); void setDoneFlag() { fDoneFlag = ~0; } protected: // redefined virtual functions
virtual char const* getAuxSDPLine(RTPSink* rtpSink,
FramedSource* inputSource);
virtual FramedSource* createNewStreamSource(unsigned clientSessionId,
unsigned& estBitrate);
virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock,
unsigned char rtpPayloadTypeIfDynamic,
FramedSource* inputSource); private:
char* fAuxSDPLine;
char fDoneFlag; // used when setting up "fAuxSDPLine"
RTPSink* fDummyRTPSink; // ditto
}; #endif
#include "DeviceServerMediaSubsession.hh"
#include "H264VideoRTPSink.hh"
#include "DeviceSource.hh"
#include "H264VideoStreamFramer.hh"
#include "H264DeviceSource.hh" DeviceServerMediaSubsession*
DeviceServerMediaSubsession::createNew(UsageEnvironment& env,
Boolean reuseFirstSource) {
return new DeviceServerMediaSubsession(env, reuseFirstSource);
}
DeviceServerMediaSubsession::DeviceServerMediaSubsession(UsageEnvironment& env,
Boolean reuseFirstSource) :
OnDemandServerMediaSubsession(env, reuseFirstSource) {
} DeviceServerMediaSubsession::~DeviceServerMediaSubsession() {
} FramedSource* DeviceServerMediaSubsession::createNewStreamSource(
unsigned /*clientSessionId*/, unsigned& estBitrate) {
DeviceSource* source = H264DeviceSource::createNew(envir());
return H264VideoStreamFramer::createNew(envir(), source);
} RTPSink* DeviceServerMediaSubsession::createNewRTPSink(Groupsock* rtpGroupsock,
unsigned char rtpPayloadTypeIfDynamic, FramedSource* /*inputSource*/) {
return H264VideoRTPSink::createNew(envir(), rtpGroupsock,
rtpPayloadTypeIfDynamic);
} static void afterPlayingDummy(void* clientData) {
DeviceServerMediaSubsession* subsess =
(DeviceServerMediaSubsession*) clientData;
subsess->afterPlayingDummy1();
} void DeviceServerMediaSubsession::afterPlayingDummy1() {
// Unschedule any pending 'checking' task:
envir().taskScheduler().unscheduleDelayedTask(nextTask());
// Signal the event loop that we're done:
setDoneFlag();
} static void checkForAuxSDPLine(void* clientData) {
DeviceServerMediaSubsession* subsess =
(DeviceServerMediaSubsession*) clientData;
subsess->checkForAuxSDPLine1();
} void DeviceServerMediaSubsession::checkForAuxSDPLine1() {
char const* dasl; if (fAuxSDPLine != NULL) {
// Signal the event loop that we're done:
setDoneFlag();
} else if (fDummyRTPSink != NULL
&& (dasl = fDummyRTPSink->auxSDPLine()) != NULL) {
fAuxSDPLine = strDup(dasl);
fDummyRTPSink = NULL; // Signal the event loop that we're done:
setDoneFlag();
} else if (!fDoneFlag) {
// try again after a brief delay:
int uSecsToDelay = 100000; // 100 ms
nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
(TaskFunc*) checkForAuxSDPLine, this);
}
}
char const* DeviceServerMediaSubsession::getAuxSDPLine(RTPSink* rtpSink,
FramedSource* inputSource) { if (fAuxSDPLine != NULL)
return fAuxSDPLine; // it's already been set up (for a previous client) if (fDummyRTPSink == NULL) { // we're not already setting it up for another, concurrent stream
// Note: For H264 video files, the 'config' information ("profile-level-id" and "sprop-parameter-sets") isn't known
// until we start reading the file. This means that "rtpSink"s "auxSDPLine()" will be NULL initially,
// and we need to start reading data from our file until this changes.
fDummyRTPSink = rtpSink; // Start reading the file:
fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this); // Check whether the sink's 'auxSDPLine()' is ready:
checkForAuxSDPLine(this);
} envir().taskScheduler().doEventLoop(&fDoneFlag); return fAuxSDPLine;
}
Live555 直播源 以及MediaSubsession的更多相关文章
- 基于vitamio的网络电视直播源码
这个项目是基于vitamio的网络电视直播源码,也是一个使用了vitamio的基于安卓的网络直播项目源码,可能现在网上已经有很多类似这样的视频播放应用了,不过这个还是相对来说比较完整的,希望这个案例能 ...
- 直播源格式转换教程——rtmp/rtsp/http/m3u8!!
之前寻找直播源,发现好多rtmp开头的,或者是rtsp开头的,但是ATV里面的个人链接是支持m3u8格式的.怎么办?小编发现了几个规律,网友可作参考.现在流行的直播地址差不多就这几种需要说明的是并不是 ...
- [转载]Fiddler为所欲为第四篇 直播源抓取与接口分析 [四]
今天的教程,主要是教大家如何进行“封包逆向”,关键词跳转,接口分析.(怎么样,是不是感觉和OD很像~~~)今天的教程我们以[麻花影视]为例,当然,其他APP的逻辑也是一样,通用的哦~ 首先需要做好准备 ...
- 【视频开发】【Live555】摄像头采集,264编码,live555直播
加入 摄像头采集和264编码,再使用live555直播 1.摄像头采集和264编码 将x264改成编码一帧的接口,码流不写入文件而是直接写入内存中(int Encode_frame 函数中). /* ...
- PotPlayer直播源分享
添加直播源方法: 央视CCTV1综合HD-1,rtsp://113.136.42.45:554/PLTV/88888888/224/3221226087/10000100000000060000000 ...
- 带货直播源码开发采用MySQL有什么优越性
MySQL是世界上最流行的开源关系数据库,带货直播源码使用MySQL,可实现分钟级别的数据库部署和弹性扩展,不仅经济实惠,而且稳定可靠,易于运维.云数据库 MySQL 提供备份恢复.监控.容灾.快速扩 ...
- 视频直播源码开发中的流媒体协议:rtmp协议
一.概念与摘要 视频直播源码的RTMP协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和互动内容).RTMP提供了一套全双工的可靠的多路复用消息服务,类似 ...
- 如何抓取直播源及视频URL地址-疯狂URL(教程)
直播源介绍 首先,我们来快速了解一下什么是直播源,所谓的直播源,其实就说推流地址,推流地址可能你也不知道是什么,那么我再简单说一下,推流地址就是,当某个直播开播的时候,需要将自己的直播状态实时的展示给 ...
- android文件管理器源码、斗鱼直播源码、企业级erp源码等
Android精选源码 文件清理管理器 自定义水平带数字的进度条以及自定义圆形带数字的进度条 利用sectionedRecyclerViewAdapter实现分组列表的recyclerView源码 流 ...
随机推荐
- MeshCollider双面化脚本
由于MeshCollider组件可以挂载多个,所以不需要Mesh重新合并了. 除了反转法线还需要反转所有三角面的顺序 脚本如下: using System.Collections; using Sys ...
- Codeforces Round #417 (Div. 2)-A. Sagheer and Crossroad
[题意概述] 在一个十字路口 ,给定红绿灯的情况, 按逆时针方向一次给出各个路口的左转,直行,右转,以及行人车道,判断汽车是否有可能撞到行人 [题目分析] 需要在逻辑上清晰,只需要把所有情况列出来即可 ...
- MySQL 连接的使用
MySQL 连接的使用 在前几章节中,我们已经学会了如果在一张表中读取数据,这是相对简单的,但是在真正的应用中经常需要从多个数据表中读取数据. 本章节我们将向大家介绍如何使用 MySQL 的 JOIN ...
- [ExtJS6学习笔记]Ext JS6主题系列 (Classic工具包)
本文作者:苏生米沿 本文地址:http://blog.csdn.net/sushengmiyan/article/details/50186709 翻译来源:http://docs.sencha.co ...
- apply函数用法
procedure: (apply proc arg1 ... args) Proc must be a procedure and args must be a list. Calls proc ...
- C语言诠释--为什么内存是线性分布的。
Author:伟易达集团软件工程师 II 杨源鑫Date :2016.11.11Subject:内存为什么是线性分布的 今天有位小伙伴问了我一个问题,问题大概是这样描述的: 师兄,我如何能够 ...
- SQLite 创建数据库(http://www.w3cschool.cc/sqlite/sqlite-create-database.html)
SQLite 创建数据库 SQLite 的 sqlite3 命令被用来创建新的 SQLite 数据库.您不需要任何特殊的权限即可创建一个数据. 语法 sqlite3 命令的基本语法如下: $sqlit ...
- JavaWeb 文件 上传 下载
文件上传下载对于一个网站来说,重要性不言而喻.今天来分享一个JavaWeb方式实现的文件上传下载的小例子. 项目依赖 项目目录 工作流程 文件上传 表单处的设置 服务器端 上传功能的实现 upload ...
- Dynamics CRM2013 在Visual Studio中开启脚本的Xrm.Page智能提示
前面篇博文http://blog.csdn.net/vic0228/article/details/49663751提到了通过引用XrmPage-vsdoc.js文件来启用Xrm.Page的智能提示, ...
- Team Foundation Server 2015 Update 2.1 发布日志
微软在 2016年5月5日发布了Visual Studio Team Foundation Server 2015 update 2.1. 下面我们来看看Update2.1中给我们带来了哪些新功能. ...