我遇到了一个问题,我在一周的大部分时间里一直在努力解决这个问题,并且尝试了至少 10 种不同的实现,但似乎都失败了。一定有什么我不明白的地方。
我正在使用 jmf 通过 rtp 传输音频。问题是客户端玩家永远不会意识到,因此,代码块,什么也没有播放。
Transmitter的代码如下:
import java.io.File;
import java.io.IOException;
import javax.media.DataSink;
import javax.media.Format;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.NoProcessorException;
import javax.media.NotRealizedError;
import javax.media.Processor;
import javax.media.control.FormatControl;
import javax.media.control.TrackControl;
import javax.media.format.AudioFormat;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
public class RTPTransmitter
{
/**
* @param args
*/
public static void main(String[] args)
{
File f = new File("streamtest.wav");
Format format;
format = new AudioFormat(AudioFormat.ULAW_RTP, 8000, 8, 1);
Processor processor = null;
try
{
processor = Manager.createProcessor(f.toURI().toURL());
} catch (IOException e)
{ …Run Code Online (Sandbox Code Playgroud) 这更像是一个概念问题,而不是技术问题.我对H.264的理解是,它依赖于过去和未来的帧来压缩视频数据.通过RTP或您选择的任何其他协议来获取完全压缩的H.264视频文件并将其流式传输是微不足道的,但是,这如何与实时视频一起使用?在实时视频中,您只能访问过去和当前帧,并且不知道视频的全长,那么H.264编解码器如何实际压缩视频并将其准备为RTP有效载荷?它只是简单地将视频缓冲并分块为任意大小的较小视频并压缩它吗?我能想到这个工作的唯一方法是将视频分成1秒钟的块,将它们压缩为单独的视频,并使它们成为RTP有效载荷.这是它的完成方式还是更多"
我阅读了RTP规范,似乎无法理解RTP数据包时间戳.我尝试在我的服务器中以不同的方式实现它但我无法让播放器正确播放.
我在这里的"错误"行为是(我使用VLC播放器将RTSP网址播放到我的服务器)我发现播放器的日志说"缓冲方式太晚"和"错误的PTS值".这意味着音频帧以某种方式到达时间戳未正确的数据包.我尝试以不同的方式实现时间戳的生成,但没有这样的运气.
我需要一些详细的资源或参考资料,这些资源或参考资料确实让我理解了RTP时间戳如何工作并生成.
我试图将我的音频呼叫强制为单声道,我愿意使用 PCMU、G.729、OPUS 和 SpeeX 作为我的编解码器来处理这个呼叫。
现在我正在使用以下代码在我的 sdp 消息中搜索所选的编解码器:
function maybePreferCodec(sdp, type, dir, codec) {
var str = type + ' ' + dir + ' codec';
if (codec === '') {
return sdp;
}
var sdpLines = sdp.split('\r\n');
// Search for m line.
var mLineIndex = findLine(sdpLines, 'm=', type);
if (mLineIndex === null) {
return sdp;
}
// If the codec is available, set it as the default in m line.
var codecIndex = findLine(sdpLines, 'a=rtpmap', codec);
console.log('codecIndex', codecIndex);
if …Run Code Online (Sandbox Code Playgroud) 我使用这些命令来发送和接收 rtp 数据:
发送 rtp 数据到 UDP 端口 5000
gst-launch-1.0 -v filesrc location = haizeiwang.mp4 ! decodebin ! x264enc ! rtph264pay ! udpsink host=192.168.1.101 port=5000
Run Code Online (Sandbox Code Playgroud)
从udp端口5000接收rtp数据并播放。
gst-launch-1.0 -v udpsrc port=5000 caps="application/x-rtp, media=video, clock-rate=90000, encoding-name=H264, payload=96, ssrc=3394826012, timestamp-offset=2215812541, seqnum-offset=46353" ! rtph264depay ! decodebin ! videoconvert ! autovideosink sync=false
Run Code Online (Sandbox Code Playgroud)
但我只能得到视频(不是很清楚),而且没有声音。我可以同时获得视频和音频吗?我应该使用哪些元素?命令应该是什么?
谢谢你。
我使用node.js 从WebRTC服务器(我使用mediasoup)获得RTP流,并从流中获取解密的RTP数据包原始数据.我想将此RTP数据转发到ffmpeg,然后我可以将其保存到文件,或将其作为RTMP流推送到其他媒体服务器.我想最好的方法是创建描述音频和视频流的SDP文件,并通过新的套接字发送数据包.
ffmpeg命令是:
ffmpeg -loglevel debug -protocol_whitelist file,crypto,udp,rtp -re -vcodec libvpx -acodec opus -i test.sdp -vcodec libx264 -acodec aac -y output.mp4
我试图通过UDP发送数据包:
v=0
o=mediasoup 7199daf55e496b370e36cd1d25b1ef5b9dff6858 0 IN IP4 192.168.193.182
s=7199daf55e496b370e36cd1d25b1ef5b9dff6858
c=IN IP4 192.168.193.182
t=0 0
m=audio 33301 RTP/AVP 111
a=rtpmap:111 /opus/48000
a=fmtp:111 minptime=10;useinbandfec=1
a=rtcp-fb:111 transport-cc
a=sendrecv
m=video 33302 RTP/AVP 100
a=rtpmap:100 /VP8/90000
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=sendrecv
Run Code Online (Sandbox Code Playgroud)
但我总是得到(删除无聊的部分):
Opening an input file: test.sdp.
[sdp @ 0x103dea0]
Format sdp probed with …Run Code Online (Sandbox Code Playgroud) 为什么我在E位为0时获得dtmf声音而在1为1时没有声音?(RTP数据包以无论哪种方式出现在wireshark中)
我可以发送一个RFC 2833 dtmf事件,如http://www.ietf.org/rfc/rfc2833.txt所述, 当未设置E位时获得以下行为:
如果7874556332111111145855885#3按下键,则会发送所有事件并显示在wireshark等程序中,但只有87456321458585#3声音.所以第一个键(我认为可能是一个单独的问题)和事件的任何重复(即11111)都听不到.
在上面链接文档的图3.9的3.9节中,它们给出了一个911示例,其中除了最后一个事件之外的所有事件都设置了E位.
当我为所有数字设置'E'位为1时,我从未发出声音事件.
我想到了一些可能的原因,但不知道它们是否是原因:
1)图2显示了96和97发送的有效载荷类型.我没有发送这些标题.在3.8节中,代码96和97被描述为"分别为冗余机制和电话事件有效载荷分配了动态有效载荷类型96和97"
2)在第3.5节"E:"中,"发送方可以延迟设置结束位,直到重新发送音频的最后一个数据包,而不是第一次传输"是否有人知道如何实际执行此操作?
3)我有一个单独的输出流,如果它可能干扰听到这个流,也会很奇怪.
4)还摆弄了时间戳间隔和RTP标记.
任何帮助是极大的赞赏.以下是相关领域的wireshark事件捕获示例:
6590 31.159045000 xx.x.x.xxx --.--.---.-- RTP EVENT Payload type=RTP Event, DTMF Pound # (end)
Real-Time Transport Protocol
Stream setup by SDP (frame 6225)
Setup frame: 6225
Setup Method: SDP
10.. .... = Version: RFC 1889 Version (2)
..0. .... = Padding: False
...0 .... = Extension: False
.... 0000 = Contributing source identifiers count: 0
0... .... = Marker: False …Run Code Online (Sandbox Code Playgroud) 我正在使用live555和ffmpeg库从服务器获取和解码RTP H264流; 视频流由ffmpeg编码,使用Baseline profile和
x264_param_default_preset(m_params, "veryfast", "zerolatency")
Run Code Online (Sandbox Code Playgroud)
我阅读了这个主题并在每帧中添加了SPS和PPS数据,这是我从网络收到的;
void ClientSink::NewFrameHandler(unsigned frameSize, unsigned numTruncatedBytes,
timeval presentationTime, unsigned durationInMicroseconds)
{
...
EncodedFrame tmp;
tmp.m_frame = std::vector<unsigned char>(m_tempBuffer.data(), m_tempBuffer.data() + frameSize);
tmp.m_duration = durationInMicroseconds;
tmp.m_pts = presentationTime;
//Add SPS and PPS data into the frame; TODO: some devices may send SPS and PPs data already into frame;
tmp.m_frame.insert(tmp.m_frame.begin(), m_spsPpsData.cbegin(), m_spsPpsData.cend());
emit newEncodedFrame( SharedEncodedFrame(tmp) );
m_frameCounter++;
this->continuePlaying();
}
Run Code Online (Sandbox Code Playgroud)
我在解码器中收到这些帧.
bool H264Decoder::decodeFrame(SharedEncodedFrame orig_frame)
{
...
while(m_packet.size > 0)
{
int got_picture;
int len …Run Code Online (Sandbox Code Playgroud) 我正在尝试根据http://www.csee.umbc.edu/~pmundur/courses/CMSC691C/lab5-kurose-ross.html示例在Java中实现RTSP协议;我已经成功地通过RTSP请求和RTP流数据包与VLC进行了成功通信;VLC无法很好地识别具有JPEG有效负载的RTP数据包。这就是为什么我认为我发送格式不正确的RTP的原因。我用Wireshark嗅探了它们,并将它们与数据包进行了比较,并从gstreamer RTSP streamer和VLc的成功RTSP通信中嗅到了它们。令我惊讶的是,我的应用程序和VLC的RTSP和RTP请求在wireshark UI中都被标记为简单的TCP和UDP数据包,而gstreamer&VLC的一个被标记为RTSP,RTP,RTCP甚至是RTSP / SDP。
我真的很困惑,我不明白为什么在某些情况下,wireshark将VLC的请求解析为纯RTSP / RTP,而我的情况则解析为纯TCP / UDP数据。至少,即使我的请求,VLC的请求也没有格式错误。
如何强制Wireshark将请求识别为某些特定协议?