/*
* 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. git 学习笔记(常用命令)

    1.新建一个文件,如果没有使用git add 命令将它提交到暂存区,那么这个文件就还没有被跟踪. 2.通过配置.gitignore文件可以指定要忽略的文件,被忽略的文件夹是不会被提交到暂存区的.所以这 ...

  2. jQuery 遍历 – 后代

    后代是子.孙.曾孙等等. 通过 jQuery,您能够向下遍历 DOM 树,以查找元素的后代. 向下遍历 DOM 树 下面是两个用于向下遍历 DOM 树的 jQuery 方法: children() f ...

  3. JAVA Eclipse使用Maven构建web项目详解(SSM框架)

    tips: 启动项目后,welcome-file的链接即为测试用例 部署maven web项目 Eclipse使用Maven构建web项目详解 pom.xml添加webapp依赖: <depen ...

  4. leetcode之Largest Rectangle in Histogram

    问题来源:Largest Rectangle in Histogram 问题描述:给定一个长度为n的直方图,我们可以在直方图高低不同的长方形之间画一个更大的长方形,求该长方形的最大面积.例如,给定下述 ...

  5. Android Material Design(一)史上最全的材料设计控件大全

    主要内容: 本文将要介绍Material design和Support library控件,主要包括TextInputLayout.SwitchCompat.SnackBar.FloatingActi ...

  6. java泛型总结(类型擦除、伪泛型、陷阱)

    JDK1.5开始实现了对泛型的支持,但是java对泛型支持的底层实现采用的是类型擦除的方式,这是一种伪泛型.这种实现方式虽然可用但有其缺陷. <Thinking in Java>的作者 B ...

  7. Android的log日志知识点剖析

    log类的继承结构 Log public final class Log extends Object java.lang.Object ↳ android.util.Log log日志的常用方法 分 ...

  8. Maven插件详解

    插件与插件目标 Maven定义了三套相互独立的生命周期,每套生命周期都有多个生命周期阶段,而这些阶段都是抽象的,不做任何工作.真正完成工作的是绑定在生命周期阶段的插件目标.插件以独立的构件形式存在,一 ...

  9. 熟悉java语言的基本使用:简单存款取款机制java实现

    最近一直没有项目做,于是我也不能这样闲着,我得开始学习新的技术,并且巩固以前自学的技术.以下就是我写的一个简单的java存取款代码,很简单,可能还有更简单的方法,目的是为了熟悉java的基本使用. p ...

  10. Java遍历时删除List、Set、Map中的元素(源码分析)

    在对List.Set.Map执行遍历删除或添加等改变集合个数的操作时,不能使用普通的while.for循环或增强for.会抛出ConcurrentModificationException异常或者没有 ...