android recorder通过rtp发送h264视频数据给vlc播放
android player通过rtp协议接收h264视频数据播放
Android recorder通过rtp发送aac数据给vlc播放
Android player实现播放来自rtp连接的aac数据的player
我们在发送端向端口40020发送数据,所以这里监听的是40020端口,payload type是97与发送端设置的一致。
audioRtpWrapper.open(40020, 97, 1000);
设置rtp callback用于接收aac原始数据。
audioRtpWrapper.setCallback { data, len ->
if (len < 4) return@setCallback
val index = indexArray.take()
if (currentTime == 0L) {
currentTime = System.currentTimeMillis()
val buffer = audioDecodeCodec.mediaCodec.getInputBuffer(index)
val time = (System.currentTimeMillis() - currentTime) * 1000
if (hasAuHeader) {
buffer?.position(0)
buffer?.put(data, 4, len - 4);
buffer?.position(0)
audioDecodeCodec.mediaCodec.queueInputBuffer(index, 0, len - 4, time, 1)
} else {
buffer?.position(0)
buffer?.put(data, 0, len);
buffer?.position(0)
audioDecodeCodec.mediaCodec.queueInputBuffer(index, 0, len, time, 1)
接收到aac数据后直接写入MediaCodec的inputbuffer,这里针对是否有au header来处理数据。如果有au header,那么跳过au header数据。au header length 和 au header共占用4 bytes。在通过index获取inputbuffer的时候要格外注意index的有效性,即index必须是mediacodec释放出来的buffer的index,否则会发送buffer写入错误。
创建MediaCodec的时候要指定采样率、通道数、格式等信息,这些信息需要与发送端保持一致。
val sampleRate = 44100
val audioFormat = MediaFormat.createAudioFormat(
MediaFormat.MIMETYPE_AUDIO_AAC,
sampleRate,
audioChannelCount
audioFormat.setByteBuffer("csd-0", audioSpecificConfig)
var currentTime = 0L
indexArray.clear()
audioDecodeCodec = object : AudioDecodeCodec(audioFormat) {
override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
indexArray.put(index)
这里的"csd-0"参数要格外的关注,因为这个参数不设置或是设置错误都会在解码过程中发生buffer的读写错误。audioSpecificConfig这个变量的生成规则可以参考下面这段代码:
private val audioChannelCount = 1;
private val audioProfile = 1
* 97000, 88200, 64000, 48000,44100, 32000, 24000, 22050,16000, 12000, 11025, 8000,7350, 0, 0, 0
private val audioIndex = 4
private val audioSpecificConfig = ByteArray(2).apply {
this[0] = ((audioProfile + 1).shl(3).and(0xff)).or(audioIndex.ushr(1).and(0xff)).toByte()
this[1] = ((audioIndex.shl(7).and(0xff)).or(audioChannelCount.shl(3).and(0xff))).toByte()
}.let {
val buffer = ByteBuffer.allocate(2)
buffer.put(it)
buffer.position(0)
buffer
当然如果不设置csd-0这个参数,那么从rtp返回的数据中有config数据也是可以的。但是rtp是广播形式的,它并不知道什么时候需要广播config数据,所以配置csd-0是比较好的选择。(注意:config数据指的是发送端的MediaCodec编码启动后生成的config 数据buffer)
首先根据mediaformat信息创建AudioTrack并进行播放,这里设置的参数要与MediaCodec设置的一致,同事这种流模式播放(MODE_STREAM)
override fun onOutputFormatChanged(codec: MediaCodec, format: MediaFormat) {
val sampleRate = format.getInteger(MediaFormat.KEY_SAMPLE_RATE)
val channelCount = format.getInteger(MediaFormat.KEY_CHANNEL_COUNT)
val minBufferSize = AudioRecord.getMinBufferSize(sampleRate, if (channelCount == 1) AudioFormat.CHANNEL_IN_MONO else AudioFormat.CHANNEL_IN_STEREO, AudioFormat.ENCODING_PCM_16BIT);
audioTrack = AudioTrack(AudioManager.STREAM_VOICE_CALL, sampleRate, channelCount, AudioFormat.ENCODING_PCM_16BIT, minBufferSize, MODE_STREAM);
audioTrack?.play();
从MediaCodec读取解码后的数据并写入AudioTrack,这里采用的是block方式写入。
override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, info: MediaCodec.BufferInfo) {
Log.d("audio_dragon","onOutputBufferAvailable $index")
kotlin.runCatching {
val buffer = codec.getOutputBuffer(index) ?: return;
buffer.position(info.offset);
audioTrack?.write(buffer, info.size, WRITE_BLOCKING);
codec.releaseOutputBuffer(index, false);
https://github.com/mjlong123123/AudioPlayer.git
我的公众号已经开通,公众号会同步发布。
欢迎关注我的公众号

一、接收数据rtp包的组包与拆包已经由rtp 库完成,这里可以从rtp库的回调直接接收到原始发送的数据。我们可以看到rtp payload指定的类型是96,96代表的就是h264视频数据类型。这里监听的是偶数端口40018,奇数端口留给rtcp使用。我们接收到的数据是nalu分片数据,我们还需要把分片数据组成完整的nalu数据。
我有一个Android项目,我需要构建一个客户端应用程序来接收UDP或RTP单播视频流并播放它们。不幸的是,我似乎无法得到这个工作,并已广泛搜索解决方案!Android上的UDP视频流我正在Xoom(Android 3.2)和Nexus S(Android 2.3.6)上进行测试,并且知道他们可以在使用MX Player(第三方媒体播放器应用程序)作为客户端时播放内容,但我无法让本地媒体播放器播放...
我已經試圖從播放器( Daroon播放器,來自 PlayStore ) 讀取它,它運行良好,所以我假設我的foolowing問題不是因為廣播。我看到,通過不同的方式向用戶展示視頻內容是可行的:使用一個新的Intent 與 ACTION_VIEW,並且Android選擇一個可以查看內容的應用程序;使用MediaPlayer類和 VideoView 。我有兩個問題,讓我們從最重要的開始: - 對於上述...
因为Android ijkplayer播放rtsp直播流在加载时延迟在5-10秒实在难以接受,再修改后解决了延迟问题,目前已达到2秒甚至秒开的效果 添加的方法:VideoOptionModel videoOptionMode0l = new VideoOptionModel(1, "analyzemaxduration", 100); VideoOptionModel videoOptionMode02 = new VideoOptionModel(1, "probesize", 10240); Video
我几周以来一直是Android开发的新手,我需要编写一个可以向用户显示UDP或RDP多播的实时流的应用程序.该流位于诸如“rtp://230.0.0.11:1234”的地址,由于此模块,WIFI将发出该流:http://www.ikusi.es/public/ctrl_public_prod.php?accion=verProducto&id_familia=34&id_gama=...
IjkPlayer播放器其实是支持RTP直播的,但是只能用ffmpeg软解码不能使用硬解码。这里将会从以下几个方面配置使用1、UDP RTP/RTMP区别2、FFMpeg推流3、IjkPlayer编译选项4、RTP硬解码支持一、RTP/RTMP区别RTMP直播是基于TCP协议,UDP RTP是基于UDP协议。也就是说RTMP将会更加可靠,而UDP RTP延时将会更低。二、FFMpeg推流关于HLS...
android:id="@+id/surface_view"
android:layout_width="250dp"
android:layout_height="250dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopO.
你创建了一个漂亮的UI,但是它很单调运行这个player可以在进入Activity或者Fragment的时候为view创建漂亮的过渡效果。将它放到Activity的onCreate()或者Fragment的onViewCreated()中。Player.init().animate(headerAction).then().animate(fabAction).then().animate(bot...
在公司一个项目中需要在android端上到媒体服务器上通过rtsp取流,由于媒体服务器统一的去前端网络摄像机取流,导致媒体服务器和和前端网络摄像机处于同一局域网内,项目需要在外网中播放视频,媒体服务器的rtsp端口554在公司路由器中已经成功的映射出去。
项目开发都是在局域网中,取流这些都是正常的视频的延迟也在可接受的范围内,也让朋友(老毛)拿着他的IPhone通过4G和wifi 在vlc上取
数据采集部分使用的是Camera2,CameraHolder是对camera2的简单封装。
Camera2有个显著的优势,他可以同时添加多个surface用于接收camer数据。
下面是通过CameraHolder启动camera的流程:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
......
封装的工具类:package com.example.voaactest;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import com.sinaapp.bashell.VoAACEncoder;import ...