|
|
|
@@ -2970,7 +2970,6 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) |
|
|
|
} |
|
|
|
|
|
|
|
if (rt->flv_header_bytes < RTMP_HEADER) { |
|
|
|
int set_data_frame = 0; |
|
|
|
const uint8_t *header = rt->flv_header; |
|
|
|
int channel = RTMP_AUDIO_CHANNEL; |
|
|
|
|
|
|
|
@@ -2991,32 +2990,8 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) |
|
|
|
if (pkttype == RTMP_PT_VIDEO) |
|
|
|
channel = RTMP_VIDEO_CHANNEL; |
|
|
|
|
|
|
|
if (pkttype == RTMP_PT_NOTIFY) { |
|
|
|
// For onMetaData and |RtmpSampleAccess packets, we want |
|
|
|
// @setDataFrame prepended to the packet before it gets sent. |
|
|
|
// However, definitely not *all* RTMP_PT_NOTIFY packets (e.g., |
|
|
|
// onTextData and onCuePoint). |
|
|
|
uint8_t commandbuffer[64]; |
|
|
|
int stringlen = 0, commandsize = size - rt->flv_header_bytes; |
|
|
|
GetByteContext gbc; |
|
|
|
|
|
|
|
// buf_temp at this point should be pointing to the RTMP command |
|
|
|
bytestream2_init(&gbc, buf_temp, commandsize); |
|
|
|
if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer), |
|
|
|
&stringlen)) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
|
|
|
if (!strcmp(commandbuffer, "onMetaData") || |
|
|
|
!strcmp(commandbuffer, "|RtmpSampleAccess")) { |
|
|
|
set_data_frame = 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (((pkttype == RTMP_PT_VIDEO || pkttype == RTMP_PT_AUDIO) && ts == 0) || |
|
|
|
pkttype == RTMP_PT_NOTIFY) { |
|
|
|
// add 12 bytes header if passing @setDataFrame |
|
|
|
if (set_data_frame) |
|
|
|
pktsize += 16; |
|
|
|
if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1], |
|
|
|
&rt->nb_prev_pkt[1], |
|
|
|
channel)) < 0) |
|
|
|
@@ -3034,10 +3009,6 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) |
|
|
|
|
|
|
|
rt->out_pkt.extra = rt->stream_id; |
|
|
|
rt->flv_data = rt->out_pkt.data; |
|
|
|
|
|
|
|
if (set_data_frame) { |
|
|
|
ff_amf_write_string(&rt->flv_data, "@setDataFrame"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
copy = FFMIN(rt->flv_size - rt->flv_off, size_temp); |
|
|
|
@@ -3048,6 +3019,33 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) |
|
|
|
if (rt->flv_off == rt->flv_size) { |
|
|
|
rt->skip_bytes = 4; |
|
|
|
|
|
|
|
if (rt->out_pkt.type == RTMP_PT_NOTIFY) { |
|
|
|
// For onMetaData and |RtmpSampleAccess packets, we want |
|
|
|
// @setDataFrame prepended to the packet before it gets sent. |
|
|
|
// However, not all RTMP_PT_NOTIFY packets (e.g., onTextData |
|
|
|
// and onCuePoint). |
|
|
|
uint8_t commandbuffer[64]; |
|
|
|
int stringlen = 0; |
|
|
|
GetByteContext gbc; |
|
|
|
|
|
|
|
bytestream2_init(&gbc, rt->flv_data, rt->flv_size); |
|
|
|
if (!ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer), |
|
|
|
&stringlen)) { |
|
|
|
if (!strcmp(commandbuffer, "onMetaData") || |
|
|
|
!strcmp(commandbuffer, "|RtmpSampleAccess")) { |
|
|
|
uint8_t *ptr; |
|
|
|
if ((ret = av_reallocp(&rt->out_pkt.data, rt->out_pkt.size + 16)) < 0) { |
|
|
|
rt->flv_size = rt->flv_off = rt->flv_header_bytes = 0; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
memmove(rt->out_pkt.data + 16, rt->out_pkt.data, rt->out_pkt.size); |
|
|
|
rt->out_pkt.size += 16; |
|
|
|
ptr = rt->out_pkt.data; |
|
|
|
ff_amf_write_string(&ptr, "@setDataFrame"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if ((ret = rtmp_send_packet(rt, &rt->out_pkt, 0)) < 0) |
|
|
|
return ret; |
|
|
|
rt->flv_size = 0; |
|
|
|
|