/*
* 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的更多相关文章

  1. 基于vitamio的网络电视直播源码

    这个项目是基于vitamio的网络电视直播源码,也是一个使用了vitamio的基于安卓的网络直播项目源码,可能现在网上已经有很多类似这样的视频播放应用了,不过这个还是相对来说比较完整的,希望这个案例能 ...

  2. 直播源格式转换教程——rtmp/rtsp/http/m3u8!!

    之前寻找直播源,发现好多rtmp开头的,或者是rtsp开头的,但是ATV里面的个人链接是支持m3u8格式的.怎么办?小编发现了几个规律,网友可作参考.现在流行的直播地址差不多就这几种需要说明的是并不是 ...

  3. [转载]Fiddler为所欲为第四篇 直播源抓取与接口分析 [四]

    今天的教程,主要是教大家如何进行“封包逆向”,关键词跳转,接口分析.(怎么样,是不是感觉和OD很像~~~)今天的教程我们以[麻花影视]为例,当然,其他APP的逻辑也是一样,通用的哦~ 首先需要做好准备 ...

  4. 【视频开发】【Live555】摄像头采集,264编码,live555直播

    加入 摄像头采集和264编码,再使用live555直播 1.摄像头采集和264编码 将x264改成编码一帧的接口,码流不写入文件而是直接写入内存中(int  Encode_frame 函数中). /* ...

  5. PotPlayer直播源分享

    添加直播源方法: 央视CCTV1综合HD-1,rtsp://113.136.42.45:554/PLTV/88888888/224/3221226087/10000100000000060000000 ...

  6. 带货直播源码开发采用MySQL有什么优越性

    MySQL是世界上最流行的开源关系数据库,带货直播源码使用MySQL,可实现分钟级别的数据库部署和弹性扩展,不仅经济实惠,而且稳定可靠,易于运维.云数据库 MySQL 提供备份恢复.监控.容灾.快速扩 ...

  7. 视频直播源码开发中的流媒体协议:rtmp协议

    一.概念与摘要 视频直播源码的RTMP协议从属于应用层,被设计用来在适合的传输协议(如TCP)上复用和打包多媒体传输流(如音频.视频和互动内容).RTMP提供了一套全双工的可靠的多路复用消息服务,类似 ...

  8. 如何抓取直播源及视频URL地址-疯狂URL(教程)

    直播源介绍 首先,我们来快速了解一下什么是直播源,所谓的直播源,其实就说推流地址,推流地址可能你也不知道是什么,那么我再简单说一下,推流地址就是,当某个直播开播的时候,需要将自己的直播状态实时的展示给 ...

  9. android文件管理器源码、斗鱼直播源码、企业级erp源码等

    Android精选源码 文件清理管理器 自定义水平带数字的进度条以及自定义圆形带数字的进度条 利用sectionedRecyclerViewAdapter实现分组列表的recyclerView源码 流 ...

随机推荐

  1. 浅析JS异步执行机制

    前言 JS异步执行机制具有非常重要的地位,尤其体现在回调函数和事件等方面.本文将针对JS异步执行机制进行一个简单的分析. 从一份代码讲起 下面是两个经典的JS定时执行函数,这两个函数的区别相信对JS有 ...

  2. delphi 线程教学第六节:TList与泛型

    第六节: TList 与泛型   TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本) ...

  3. git 覆盖本地变化

    git fetch && git reset --hard origin/master

  4. 【mybatis深度历险系列】mybatis中的高级映射一对一、一对多、多对多

    学习hibernate的时候,小编已经接触多各种映射,mybatis中映射有到底是如何运转的,今天这篇博文,小编主要来简单的介绍一下mybatis中的高级映射,包括一对一.一对多.多对多,希望多有需要 ...

  5. Swift运行时简介

    因为Swift的操作在高层并且也得与Objc联合起来干活,用Swift写的程序一般会被Objc和Swift运行时处理.因为Swift的本性--换句话说,它是一门静态语言--Swift运行时在一些关键地 ...

  6. [Python]print vs sys.stdout.write

    之前只是在项目中看到过,没怎么注意,正好跟对象一起看python学习手册,看到了这个部分于是来研究下. python版本 2.7.x os  win7 print  一般就是执行脚本的时候,把信息直接 ...

  7. Nginx的负载均衡 - 一致性哈希 (Consistent Hash)

    Nginx版本:1.9.1 我的博客:http://blog.csdn.net/zhangskd 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减 ...

  8. JBOSS EAP6 系列二 客户端访问位于EAR中的EJB时,jndi name要遵守的规则

    EJB 的 jndi语法(在整个调用远程ejb的过程中语法的遵循是相当重要的) 参见jboss-as-quickstarts-7.1.1.CR2\ejb-remote\client\src\main\ ...

  9. 剑指offer面试题3 二维数组中的查找 (java)

    注:java主要可以利用字符串的length方法求出长度解决这个问题带来方便 public class FindNum { public static void main(String[] args) ...

  10. 【Netty源码分析】客户端connect服务端过程

    上一篇博客[Netty源码分析]Netty服务端bind端口过程 我们介绍了服务端绑定端口的过程,这一篇博客我们介绍一下客户端连接服务端的过程. ChannelFuture future = boos ...