mirror of
https://gitee.com/xia-chu/ZLMediaKit.git
synced 2026-06-14 19:47:49 +08:00
Fix RTMP proxy audio forwarding (#4745)
Some checks failed
Android / build (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Docker / build (push) Has been cancelled
DockerPy / build (push) Has been cancelled
Linux / build (push) Has been cancelled
Linux_Python / build (push) Has been cancelled
macOS / build (push) Has been cancelled
macOS_Python / build (push) Has been cancelled
Windows / build (push) Has been cancelled
Windows_Python / build (push) Has been cancelled
Some checks failed
Android / build (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Docker / build (push) Has been cancelled
DockerPy / build (push) Has been cancelled
Linux / build (push) Has been cancelled
Linux_Python / build (push) Has been cancelled
macOS / build (push) Has been cancelled
macOS_Python / build (push) Has been cancelled
Windows / build (push) Has been cancelled
Windows_Python / build (push) Has been cancelled
## Summary This fixes RTMP playback audio corruption and VLC playback compatibility when proxying some upstream RTMP streams through `addStreamProxy`. In the reproduced case, HTTP-FLV playback was normal, while RTMP playback had missing audio or occasional sharp noise in VLC. ## Root cause - RTMP aggregate message parsing copied the 4-byte `PreviousTagSize` field into the sub-message payload. This shifts the payload boundary and can corrupt subsequent audio packets. - `RtmpSession::onSendMedia` forwarded proxied audio/video packets with the packet's original chunk stream id. This can make audio packets use an unsuitable chunk id for RTMP playback. - The RTMP play response emitted non-essential `MSG_DATA` notifications (`|RtmpSampleAccess` and `NetStream.Data.Start`). FFmpeg tolerates these, but VLC may expose them as an extra `Data: none` stream and handle RTMP playback poorly. ## Changes - Exclude `PreviousTagSize` from aggregate sub-message payloads while still skipping it when advancing the parser cursor. - Send audio packets on `CHUNK_AUDIO` and video packets on `CHUNK_VIDEO` from `STREAM_MEDIA`; keep the original values for other packet types. - Avoid sending the non-essential RTMP play data notifications before metadata/config/media packets. ## Validation - Built `MediaServer` locally in Debug mode. - Proxied four live RTMP test streams via `addStreamProxy`. - Verified local RTMP and HTTP-FLV playback expose AAC audio tracks. - Decoded RTMP audio with `ffmpeg -xerror`; all tested streams completed without AAC decode errors. - Verified the VLC compatibility change removes the extra `Data: none` stream from RTMP output while preserving Video + Audio streams. - Built and deployed a Docker image locally with docker compose and re-tested RTMP/FLV audio playback.
This commit is contained in:
parent
4a2c4d0e98
commit
eeb2693f22
@ -910,10 +910,7 @@ void RtmpProtocol::handle_chunk(RtmpPacket::Ptr packet) {
|
|||||||
ts |= (*ptr << 24);
|
ts |= (*ptr << 24);
|
||||||
ptr += 1;
|
ptr += 1;
|
||||||
ptr += 3;
|
ptr += 3;
|
||||||
// 参考FFmpeg多拷贝了4个字节 [AUTO-TRANSLATED:d8aae4ae]
|
if (ptr + size + 4 > ptr_tail) {
|
||||||
// Reference FFmpeg copied 4 more bytes
|
|
||||||
size += 4;
|
|
||||||
if (ptr + size > ptr_tail) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!first_message) {
|
if (!first_message) {
|
||||||
@ -930,7 +927,7 @@ void RtmpProtocol::handle_chunk(RtmpPacket::Ptr packet) {
|
|||||||
sub_packet.stream_index = chunk_data.stream_index;
|
sub_packet.stream_index = chunk_data.stream_index;
|
||||||
sub_packet.chunk_id = chunk_data.chunk_id;
|
sub_packet.chunk_id = chunk_data.chunk_id;
|
||||||
handle_chunk(std::move(sub_packet_ptr));
|
handle_chunk(std::move(sub_packet_ptr));
|
||||||
ptr += size;
|
ptr += size + 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -273,17 +273,7 @@ void RtmpSession::sendPlayResponse(const string &err, const RtmpMediaSource::Ptr
|
|||||||
"details", _media_info.stream,
|
"details", _media_info.stream,
|
||||||
"clientid", "0"});
|
"clientid", "0"});
|
||||||
|
|
||||||
// |RtmpSampleAccess(true, true)
|
|
||||||
AMFEncoder invoke;
|
AMFEncoder invoke;
|
||||||
invoke << "|RtmpSampleAccess" << true << true;
|
|
||||||
sendResponse(MSG_DATA, invoke.data());
|
|
||||||
|
|
||||||
//onStatus(NetStream.Data.Start)
|
|
||||||
invoke.clear();
|
|
||||||
AMFValue obj(AMF_OBJECT);
|
|
||||||
obj.set("code", "NetStream.Data.Start");
|
|
||||||
invoke << "onStatus" << obj;
|
|
||||||
sendResponse(MSG_DATA, invoke.data());
|
|
||||||
|
|
||||||
//onStatus(NetStream.Play.PublishNotify)
|
//onStatus(NetStream.Play.PublishNotify)
|
||||||
sendStatus({ "level", "status",
|
sendStatus({ "level", "status",
|
||||||
@ -587,7 +577,17 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
|
void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
|
||||||
sendRtmp(pkt->type_id, pkt->stream_index, pkt, pkt->time_stamp, pkt->chunk_id);
|
switch (pkt->type_id) {
|
||||||
|
case MSG_AUDIO:
|
||||||
|
sendRtmp(pkt->type_id, STREAM_MEDIA, pkt, pkt->time_stamp, CHUNK_AUDIO);
|
||||||
|
break;
|
||||||
|
case MSG_VIDEO:
|
||||||
|
sendRtmp(pkt->type_id, STREAM_MEDIA, pkt, pkt->time_stamp, CHUNK_VIDEO);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sendRtmp(pkt->type_id, pkt->stream_index, pkt, pkt->time_stamp, pkt->chunk_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RtmpSession::close(MediaSource &sender) {
|
bool RtmpSession::close(MediaSource &sender) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user