void H264Packetizer::pushBuffer(const uint8_t* const inBuffer, size_t inSize, IMetadata& inMetadata) { std::vector<uint8_t>& outBuffer = m_outbuffer; outBuffer.clear(); uint8_t nal_type = inBuffer[4] & 0x1F; int flags = 0; const int flags_size = 5; const int ts = inMetadata.timestampDelta; bool is_config = (nal_type == 7 || nal_type == 8); flags = FLV_CODECID_H264; auto output = m_output.lock(); RTMPMetadata_t outMeta(inMetadata.timestampDelta); switch(nal_type) { case 7: if(m_sps.size() == 0) { m_sps.resize(inSize-4); memcpy(&m_sps[0], inBuffer+4, inSize-4); } return; case 8: if(m_pps.size() == 0) { m_pps.resize(inSize-4); memcpy(&m_pps[0], inBuffer+4, inSize-4); } flags |= FLV_FRAME_KEY; break; case 5: flags |= FLV_FRAME_KEY; break; default: flags |= FLV_FRAME_INTER; break; } if(output) { std::vector<uint8_t> conf; if(is_config && m_sps.size() > 0 && m_pps.size() > 0 ) { conf = configurationFromSpsAndPps(); inSize = conf.size(); } outBuffer.reserve(inSize + flags_size); put_byte(outBuffer, flags); put_byte(outBuffer, !is_config); put_be24(outBuffer, 0); if(is_config) { // create modified SPS/PPS buffer if(m_sps.size() > 0 && m_pps.size() > 0 && !m_sentConfig) { put_buff(outBuffer, &conf[0], conf.size()); m_sentConfig = true; } else { return; } } else { put_buff(outBuffer, inBuffer, inSize); } static auto prev_time = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now(); auto m_micros = std::chrono::duration_cast<std::chrono::microseconds>(now - prev_time).count(); static uint64_t total = 0; static uint64_t count = 0; total+=m_micros; count++; prev_time = now; outMeta.setData(ts, static_cast<int>(outBuffer.size()), FLV_TAG_TYPE_VIDEO, kVideoChannelStreamId); output->pushBuffer(&outBuffer[0], outBuffer.size(), outMeta); } }
void H264Packetizer::pushBuffer(const uint8_t* const inBuffer, size_t inSize, IMetadata& inMetadata) { std::vector<uint8_t>& outBuffer = m_outbuffer; outBuffer.clear(); uint8_t nal_type = inBuffer[4] & 0x1F; int flags = 0; const int flags_size = 5; int dts = inMetadata.dts ; int pts = inMetadata.pts + m_ctsOffset; // correct for pts < dts which some players (ffmpeg) don't like dts = dts > 0 ? dts : pts - m_ctsOffset ; bool is_config = (nal_type == 7 || nal_type == 8); flags = FLV_CODECID_H264; auto output = m_output.lock(); switch(nal_type) { case 7: if(m_sps.size() == 0) { m_sps.resize(inSize-4); memcpy(&m_sps[0], inBuffer+4, inSize-4); } break; case 8: if(m_pps.size() == 0) { m_pps.resize(inSize-4); memcpy(&m_pps[0], inBuffer+4, inSize-4); } flags |= FLV_FRAME_KEY; break; case 5: flags |= FLV_FRAME_KEY; break; default: flags |= FLV_FRAME_INTER; break; } if(output) { RTMPMetadata_t outMeta(dts); std::vector<uint8_t> conf; if(is_config && m_sps.size() > 0 && m_pps.size() > 0 ) { conf = configurationFromSpsAndPps(); inSize = conf.size(); } outBuffer.reserve(inSize + flags_size); put_byte(outBuffer, flags); put_byte(outBuffer, !is_config); put_be24(outBuffer, pts - dts); // Decoder delay if(is_config ) { // create modified SPS/PPS buffer if(m_sps.size() > 0 && m_pps.size() > 0 && !m_sentConfig && (flags & FLV_FRAME_KEY)) { put_buff(outBuffer, &conf[0], conf.size()); m_sentConfig = true; } else { return; } } else { put_buff(outBuffer, inBuffer, inSize); } outMeta.setData(dts, static_cast<int>(outBuffer.size()), RTMP_PT_VIDEO, kVideoChannelStreamId, nal_type == 5); output->pushBuffer(&outBuffer[0], outBuffer.size(), outMeta); } }