调用RTMP_SendPacket经常会出现阻塞现象

RTMP直播流阻塞问题
本文探讨了使用librtmp发布H264直播流时遇到的RTMP_SendPacket阻塞问题,尤其是在无线网络环境下更为明显。文章详细记录了问题排查过程及解决方案,包括通过设置socket超时时间和检测网络连接状态来避免阻塞。
部署运行你感兴趣的模型镜像

http://bbs.youkuaiyun.com/topics/391023560


回复次数:7




您可能感兴趣的与本文相关的镜像

Dify

Dify

AI应用
Agent编排

Dify 是一款开源的大语言模型(LLM)应用开发平台,它结合了 后端即服务(Backend as a Service) 和LLMOps 的理念,让开发者能快速、高效地构建和部署生产级的生成式AI应用。 它提供了包含模型兼容支持、Prompt 编排界面、RAG 引擎、Agent 框架、工作流编排等核心技术栈,并且提供了易用的界面和API,让技术和非技术人员都能参与到AI应用的开发过程中

librtmp里面的发包函数如下: int RTMP_SendPacket(RTMP *r, RTMPPacket *packet, int queue) { const RTMPPacket *prevPacket; uint32_t last = 0; int nSize; int hSize, cSize; char *header, *hptr, *hend, hbuf[RTMP_MAX_HEADER_SIZE], c; uint32_t t; char *buffer, *tbuf = NULL, *toff = NULL; int nChunkSize; int tlen; if (packet->m_nChannel >= r->m_channelsAllocatedOut) { int n = packet->m_nChannel + 10; RTMPPacket **packets = realloc(r->m_vecChannelsOut, sizeof(RTMPPacket*) * n); if (!packets) { free(r->m_vecChannelsOut); r->m_vecChannelsOut = NULL; r->m_channelsAllocatedOut = 0; return FALSE; } r->m_vecChannelsOut = packets; memset(r->m_vecChannelsOut + r->m_channelsAllocatedOut, 0, sizeof(RTMPPacket*) * (n - r->m_channelsAllocatedOut)); r->m_channelsAllocatedOut = n; } prevPacket = r->m_vecChannelsOut[packet->m_nChannel]; if (prevPacket && packet->m_headerType != RTMP_PACKET_SIZE_LARGE) { /* compress a bit by using the prev packet's attributes */ if (prevPacket->m_nBodySize == packet->m_nBodySize && prevPacket->m_packetType == packet->m_packetType && packet->m_headerType == RTMP_PACKET_SIZE_MEDIUM) packet->m_headerType = RTMP_PACKET_SIZE_SMALL; if (prevPacket->m_nTimeStamp == packet->m_nTimeStamp && packet->m_headerType == RTMP_PACKET_SIZE_SMALL) packet->m_headerType = RTMP_PACKET_SIZE_MINIMUM; last = prevPacket->m_nTimeStamp; } if (packet->m_headerType > 3) /* sanity */ { RTMP_Log(RTMP_LOGERROR, "sanity failed!! trying to send header of type: 0x%02x.", (unsigned char)packet->m_headerType); return FALSE; } nSize = packetSize[packet->m_headerType]; hSize = nSize; cSize = 0; t = packet->m_nTimeStamp - last; if (packet->m_body) { header = packet->m_body - nSize; hend = packet->m_body; } else { header = hbuf + 6; hend = hbuf + sizeof(hbuf); } if (packet->m_nChannel > 319) cSize = 2; else if (packet->m_nChannel > 63) cSize = 1; if (cSize) { header -= cSize; hSize += cSize; } if (t >= 0xffffff) { header -= 4; hSize += 4; RTMP_Log(RTMP_LOGWARNING, "Larger timestamp than 24-bit: 0x%x", t); } hptr = header; c = packet->m_headerType << 6; switch (cSize) { case 0: c |= packet->m_nChannel; break; case 1: break; case 2: c |= 1; break; } *hptr++ = c; if (cSize) { int tmp = packet->m_nChannel - 64; *hptr++ = tmp & 0xff; if (cSize == 2) *hptr++ = tmp >> 8; } if (nSize > 1) { hptr = AMF_EncodeInt24(hptr, hend, t > 0xffffff ? 0xffffff : t); } if (nSize > 4) { hptr = AMF_EncodeInt24(hptr, hend, packet->m_nBodySize); *hptr++ = packet->m_packetType; } if (nSize > 8) hptr += EncodeInt32LE(hptr, packet->m_nInfoField2); if (t >= 0xffffff) hptr = AMF_EncodeInt32(hptr, hend, t); nSize = packet->m_nBodySize; buffer = packet->m_body; nChunkSize = r->m_outChunkSize; RTMP_Log(RTMP_LOGDEBUG2, "%s: fd=%d, size=%d", __FUNCTION__, r->m_sb.sb_socket, nSize); /* send all chunks in one HTTP request */ if (r->Link.protocol & RTMP_FEATURE_HTTP) { int chunks = (nSize+nChunkSize-1) / nChunkSize; if (chunks > 1) { tlen = chunks * (cSize + 1) + nSize + hSize; tbuf = malloc(tlen); if (!tbuf) return FALSE; toff = tbuf; } } while (nSize + hSize) { int wrote; if (nSize < nChunkSize) nChunkSize = nSize; RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)header, hSize); RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)buffer, nChunkSize); if (tbuf) { memcpy(toff, header, nChunkSize + hSize); toff += nChunkSize + hSize; } else { wrote = WriteN(r, header, nChunkSize + hSize); if (!wrote) return FALSE; } nSize -= nChunkSize; buffer += nChunkSize; hSize = 0; if (nSize > 0) { header = buffer - 1; hSize = 1; if (cSize) { header -= cSize; hSize += cSize; } if (t >= 0xffffff) { header -= 4; hSize += 4; } *header = (0xc0 | c); if (cSize) { int tmp = packet->m_nChannel - 64; header[1] = tmp & 0xff; if (cSize == 2) header[2] = tmp >> 8; } if (t >= 0xffffff) { char* extendedTimestamp = header + 1 + cSize; AMF_EncodeInt32(extendedTimestamp, extendedTimestamp + 4, t); } } } if (tbuf) { int wrote = WriteN(r, tbuf, toff-tbuf); free(tbuf); tbuf = NULL; if (!wrote) return FALSE; } /* we invoked a remote method */ if (packet->m_packetType == RTMP_PACKET_TYPE_INVOKE) { AVal method; char *ptr; ptr = packet->m_body + 1; AMF_DecodeString(ptr, &method); RTMP_Log(RTMP_LOGDEBUG, "Invoking %s", method.av_val); /* keep it in call queue till result arrives */ if (queue) { int txn; ptr += 3 + method.av_len; txn = (int)AMF_DecodeNumber(ptr); AV_queue(&r->m_methodCalls, &r->m_numCalls, &method, txn); } } if (!r->m_vecChannelsOut[packet->m_nChannel]) r->m_vecChannelsOut[packet->m_nChannel] = malloc(sizeof(RTMPPacket)); memcpy(r->m_vecChannelsOut[packet->m_nChannel], packet, sizeof(RTMPPacket)); return TRUE; } 帮我详细理解一些发包的流程,并告诉我r->m_outChunkSize的使用作用
最新发布
11-08
/* ======================================================================== Routine Description: API for MLME to transmit management frame to AP (BSS Mode) or station (IBSS Mode) Arguments: pAd Pointer to our adapter pData Pointer to the outgoing 802.11 frame Length Size of outgoing management frame Return Value: NDIS_STATUS_FAILURE NDIS_STATUS_PENDING NDIS_STATUS_SUCCESS IRQL = PASSIVE_LEVEL IRQL = DISPATCH_LEVEL Note: ======================================================================== */ NDIS_STATUS MiniportMMRequest(RTMP_ADAPTER *pAd, UCHAR QueIdx, UCHAR *pData, UINT Length) { PNDIS_PACKET pkt; NDIS_STATUS Status; BOOLEAN bUseDataQ = FALSE, FlgDataQForce = FALSE; HEADER_802_11 *pHead = (HEADER_802_11 *)pData; struct wifi_dev *wdev = NULL; struct wifi_dev_ops *ops = NULL; INT hw_len; UCHAR hw_hdr[40]; struct tr_counter *tr_cnt = &pAd->tr_ctl.tr_cnt; struct _RTMP_CHIP_CAP *cap = hc_get_chip_cap(pAd->hdev_ctrl); #ifdef WF_RESET_SUPPORT if (pAd->wf_reset_in_progress == TRUE) return NDIS_STATUS_SUCCESS; #endif hw_len = cap->tx_hw_hdr_len; ASSERT((sizeof(hw_hdr) > hw_len)); NdisZeroMemory(&hw_hdr, hw_len); ASSERT(Length <= MAX_MGMT_PKT_LEN); Status = RTMPAllocateNdisPacket(pAd, &pkt, (UCHAR *)&hw_hdr[0], hw_len, pData, Length); if (Status != NDIS_STATUS_SUCCESS) { MTWF_DBG(pAd, DBG_CAT_TX, DBG_SUBCAT_ALL, DBG_LVL_ERROR, "MiniportMMRequest (error:: can't allocate NDIS PACKET)\n"); return NDIS_STATUS_FAILURE; } wdev = wdev_search_by_address(pAd, pHead->Addr2); if (wdev) { ops = wdev->wdev_ops; } else { RELEASE_NDIS_PACKET(pAd, pkt, NDIS_STATUS_FAILURE); tr_cnt->tx_invalid_wdev++; return NDIS_STATUS_FAILURE; } if ((QueIdx & MGMT_USE_QUEUE_FLAG) == MGMT_USE_QUEUE_FLAG) { bUseDataQ = TRUE; QueIdx &= (~MGMT_USE_QUEUE_FLAG); } if (bUseDataQ) FlgDataQForce = TRUE; #ifdef WIFI_DIAG diag_miniport_mm_request(pAd, pData, Length); #endif #if defined(CONFIG_STA_SUPPORT) || defined(APCLI_SUPPORT) if (wdev->wdev_type == WDEV_TYPE_STA) RTMPWakeUpWdev(pAd, wdev); #endif /* CONFIG_STA_SUPPORT || APCLI_SUPPORT */ RTMP_SET_PACKET_TYPE(pkt, TX_MGMT); Status = send_mlme_pkt(pAd, pkt, wdev, QueIdx, bUseDataQ); return Status; }解析该函数
10-08
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值