package com.live.muxer;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.util.Log;
import com.live.simplertmp.DefaultRtmpPublisher;
import com.live.simplertmp.RtmpHandler;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 主要对视音频原始数据h264和aac数据进行flv tag格式的封装,然后将封装好的数据传递给rtmp模块进行推理发送
* Created by winlin on 5/2/15.
* Updated by leoma on 4/1/16.
* to POST the h.264/avc annexb frame over RTMP.
* @see android.media.MediaMuxer https://developer.android.com/reference/android/media/MediaMuxer.html
*/
public class SrsFlvMuxer {
private static final int VIDEO_ALLOC_SIZE = 128 * 1024; //
private static final int AUDIO_ALLOC_SIZE = 4 * 1024;
private volatile boolean started = false;
private DefaultRtmpPublisher publisher;
private Thread worker;
private final Object txFrameLock = new Object();
private SrsFlv flv = new SrsFlv(); //flv格式封装相关
private boolean needToFindKeyFrame = true;
private SrsFlvFrame mVideoSequenceHeader; //视频头帧
private SrsFlvFrame mAudioSequenceHeader; //音频头帧
private SrsAllocator mVideoAllocator = new SrsAllocator(VIDEO_ALLOC_SIZE);
private SrsAllocator mAudioAllocator = new SrsAllocator(AUDIO_ALLOC_SIZE);
//ConcurrentLinkedQueue是一个基于链表的无界非阻塞队列,并且是线程安全的,它采用的是先进先出的规则,当我们增加一个元素时,
// 它会添加到队列的末尾,当我们取一个元素时,它会返回一个队列头部的元素,用来实现高并发的一个队列
private ConcurrentLinkedQueue<SrsFlvFrame> mFlvTagCache = new ConcurrentLinkedQueue<>();
private static final int VIDEO_TRACK = 100;
private static final int AUDIO_TRACK = 101;
private static final String TAG = "SrsFlvMuxer";
/**
* constructor.
* @param handler the rtmp event handler.
*/
public SrsFlvMuxer(RtmpHandler handler) {
publisher = new DefaultRtmpPublisher(handler);
}
/**
* get cached video frame number in publisher
*/
public AtomicInteger getVideoFrameCacheNumber() {
return publisher == null ? null : publisher.getVideoFrameCacheNumber();
}
/**
* set video resolution for publisher
* @param width width
* @param height height
*/
public void setVideoResolution(int width, int height) {
if (publisher != null) {
publisher.setVideoResolution(width, height);
}
}
/**
* Adds a track with the specified format.
* @param format The media format for the track.
* @return The track index for this newly added track.
*/
public int addTrack(MediaFormat format) {
if (format.getString(MediaFormat.KEY_MIME).contentEquals("video/avc")) {
flv.setVideoTrack(format);
return VIDEO_TRACK;
} else {
flv.setAudioTrack(format);
return AUDIO_TRACK;
}
}
//rtmp断开连接
private void disconnect() {
try {
publisher.close();
} catch (IllegalStateException e) {
// Ignore illegal state.
}
mVideoSequenceHeader = null;
mAudioSequenceHeader = null;
Log.i(TAG, "worker: disconnect ok.");
}
private boolean connect(String url) {
boolean connected = false;
Log.i(TAG, String.format("worker: connecting to RTMP server by url=%s\n", url));
if (publisher.connect(url)) {
connected = publisher.publish("live");
}
mVideoSequenceHeader = null;
mAudioSequenceHeader = null;
return connected;
}
//通过publisher推送flv Tag数据
private void sendFlvTag(SrsFlvFrame frame) {
if (frame == null) {
return;
}
if (frame.isVideo()) {
if (frame.isKeyFrame()) {
Log.i(TAG, String.format("worker: send frame type=%d, dts=%d, size=%dB",
frame.type, frame.dts, frame.flvTag.array().length));
}
publisher.publishVideoData(frame.flvTag.array(), frame.flvTag.size(), frame.dts);
mVideoAllocator.release(frame.flvTag);
} else if (frame.isAudio()) {
publisher.publishAudioData(frame.flvTag.array(), frame.flvTag.size(), frame.dts);
mAudioAllocator.release(frame.flvTag);
}
}
/**
* start to the remote server for remux.
*/
public void start(final String rtmpUrl) {
started = true;
worker = new Thread(new Runnable() {
@Override
public void run() {
//连接url
if (!connect(rtmpUrl)) {
return;
}
while (!Thread.interrupted()) {
//循环从缓冲中取数据,因为是非阻塞队列,所以要先判断是否为空
while (!mFlvTagCache.isEmpty()) {
//如果队列为空,则返回null
SrsFlvFrame frame = mFlvTagCache.poll();
if (frame.isSequenceHeader()) {
if (frame.isVideo()) {
mVideoSequenceHeader = frame;
sendFlvTag(mVideoSequenceHeader);
} else if (frame.isAudio()) {
mAudioSequenceHeader = frame;
sendFlvTag(mAudioSequenceHeader);
}
} else {
if (frame.isVideo() && mVideoSequenceHeader != null) {
sendFlvTag(frame);
} else if (frame.isAudio() && mAudioSequenceHeader != null) {
sendFlvTag(frame);
}
}
}
// Waiting for next frame
synchronized (txFrameLock) {
try {
// isEmpty() may take some time, so we set timeout to detect next frame
txFrameLock.wait(500);
} catch (InterruptedException ie) {
worker.interrupt();
}
}
}
}
});
worker.start();
}
/**
* stop the muxer, disconnect RTMP connection.
*/
public void stop() {
started = false;
mFlvTagCache.clear();
if (worker != null) {
worker.interrupt();
try {
worker.join();
} catch (InterruptedException e) {
e.printStackTrace();
worker.interrupt();
}
worker = null;
}
flv.reset();
needToFindKeyFrame = true;
Log.i(TAG, "SrsFlvMuxer closed");
// We should not block the main thread
new Thread(new Runnable() {
@Override
public void run() {
disconnect();
}
}).start();
}
/**
* send the annexb frame over RTMP.
* @param trackIndex The track index for this sample.
* @param byteBuf The encoded sample.
* @param bufferInfo The buffer information related to this sample.
*/
public void writeSampleData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo) {
if (bufferInfo.offset > 0) {
Log.w(TAG, String.format("encoded frame %dB, offset=%d pts=%dms",
bufferInfo.size, bufferInfo.offset, bufferInfo.presentationTimeUs / 1000
));
}
if (VIDEO_TRACK == trackIndex) {
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
C和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zipC和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zipC和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zipC和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zipC和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zipC和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zipC和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zip 【资源说明】 适用人群:该项目属于高分优质项目,上传之前都本地运行验证过。适合小白、高校学生、教师、科研人员、公司员工下载学习借鉴使用。 用途:学习借鉴,也可在此基础上二次开发,当然也可以直接用于课设、作业、毕设、实际项目等。 技术支持:关于项目的技术细节或更详细的介绍,可以私信与我沟通,或看项目内的项目说明(若有)、代码等,很乐意交流学习。 【特别强调】 若自己基础实在太差,自己不懂运行,可以与我私聊,可远程教学指导。当然也可以做项目二次开发和定制。
资源推荐
资源详情
资源评论
收起资源包目录
C和C++开发基于FFmpeg和OpenGL的视频播放器项目源码.zip (2000个子文件)
libfdk-aac.a 6.87MB
libfdk-aac.a 6.87MB
libyuv.a 2.18MB
libyuv.a 2.18MB
libx264.a 1.12MB
libx264.a 1.12MB
librtmp.a 81KB
librtmp.a 81KB
gradlew.bat 2KB
gradlew.bat 2KB
WavReader.c 5KB
WavReader.c 5KB
MediaPlayer.cpp 42KB
MediaPlayer.cpp 42KB
TDStretch.cpp 35KB
TDStretch.cpp 35KB
com.eplayer.EasyMediaPlayer.cpp 27KB
com.eplayer.EasyMediaPlayer.cpp 27KB
MediaMetadataRetriever.cpp 26KB
MediaMetadataRetriever.cpp 26KB
com_live_LiveNativeManager.cpp 25KB
com_live_LiveNativeManager.cpp 25KB
MediaSync.cpp 22KB
MediaSync.cpp 22KB
RtmpLivePush.cpp 20KB
RtmpLivePush.cpp 20KB
VideoEncoder.cpp 18KB
VideoEncoder.cpp 18KB
com_eplayer_EMeiaMetadataRetriever.cpp 17KB
com_eplayer_EMeiaMetadataRetriever.cpp 17KB
SoundTouch.cpp 17KB
SoundTouch.cpp 17KB
AudioResampler.cpp 16KB
AudioResampler.cpp 16KB
SLESDevice.cpp 15KB
SLESDevice.cpp 15KB
EMediaPlayer.cpp 14KB
EMediaPlayer.cpp 14KB
mmx_optimized.cpp 13KB
mmx_optimized.cpp 13KB
sse_optimized.cpp 13KB
sse_optimized.cpp 13KB
GLESDevice.cpp 12KB
GLESDevice.cpp 12KB
AudioEncoder.cpp 12KB
AudioEncoder.cpp 12KB
JNIHelp.cpp 11KB
JNIHelp.cpp 11KB
vecmath.cpp 10KB
vecmath.cpp 10KB
BPMDetect.cpp 10KB
BPMDetect.cpp 10KB
OpenGLUtils.cpp 10KB
OpenGLUtils.cpp 10KB
FIRFilter.cpp 10KB
FIRFilter.cpp 10KB
glm.cpp 9KB
glm.cpp 9KB
GLInputYUV420PFilter.cpp 9KB
GLInputYUV420PFilter.cpp 9KB
YuvUtil.cpp 9KB
YuvUtil.cpp 9KB
FIFOSampleBuffer.cpp 8KB
FIFOSampleBuffer.cpp 8KB
PeakFinder.cpp 8KB
PeakFinder.cpp 8KB
Metadata.cpp 8KB
Metadata.cpp 8KB
RateTransposer.cpp 8KB
RateTransposer.cpp 8KB
InterpolateLinear.cpp 8KB
InterpolateLinear.cpp 8KB
RenderNodeList.cpp 8KB
RenderNodeList.cpp 8KB
EglHelper.cpp 7KB
EglHelper.cpp 7KB
dummy.cpp 7KB
dummy.cpp 7KB
VideoDecoder.cpp 7KB
VideoDecoder.cpp 7KB
AAFilter.cpp 6KB
AAFilter.cpp 6KB
InterpolateCubic.cpp 6KB
InterpolateCubic.cpp 6KB
FFmpegUtils.cpp 6KB
FFmpegUtils.cpp 6KB
PlayerState.cpp 6KB
PlayerState.cpp 6KB
GLFilter.cpp 6KB
GLFilter.cpp 6KB
YuvProcess.cpp 6KB
YuvProcess.cpp 6KB
CoordinateUtils.cpp 6KB
CoordinateUtils.cpp 6KB
InterpolateShannon.cpp 6KB
InterpolateShannon.cpp 6KB
AVQueue.cpp 5KB
AVQueue.cpp 5KB
FilterManager.cpp 5KB
FilterManager.cpp 5KB
共 2000 条
- 1
- 2
- 3
- 4
- 5
- 6
- 20
资源评论
Scikit-learn
- 粉丝: 4289
- 资源: 1868
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功