void AACPacketizer::pushBuffer(const uint8_t* const inBuffer, size_t inSize, IMetadata& metadata) { const auto now = std::chrono::steady_clock::now(); const uint64_t bufferDuration(metadata.timestampDelta * 1000000.); const double nowmicros (std::chrono::duration_cast<std::chrono::microseconds>(now - m_epoch).count()); const auto micros = std::floor(nowmicros / double(bufferDuration)) * bufferDuration; std::vector<uint8_t> & outBuffer = m_outbuffer; outBuffer.clear(); int flags = 0; const int flags_size = 2; //static int prev_ts = 0; int ts = micros / 1000; // m_audioTs * 1000.;// auto output = m_output.lock(); RTMPMetadata_t outMeta(metadata.timestampDelta); if(output) { flags = FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT | FLV_STEREO; outBuffer.reserve(inSize + flags_size); put_byte(outBuffer, flags); put_byte(outBuffer, m_sentAudioConfig); if(!m_sentAudioConfig) { m_sentAudioConfig = true; const char hdr[2] = { 0x12,0x10 }; put_buff(outBuffer, (uint8_t*)hdr, 2); } else { put_buff(outBuffer, inBuffer, inSize); m_audioTs += metadata.timestampDelta; } outMeta.setData(ts, static_cast<int>(outBuffer.size()), FLV_TAG_TYPE_AUDIO, kAudioChannelStreamId); output->pushBuffer(&outBuffer[0], outBuffer.size(), outMeta); } }
void AACPacketizer::pushBuffer(const uint8_t* const inBuffer, size_t inSize, IMetadata& metadata) { std::vector<uint8_t> & outBuffer = m_outbuffer; outBuffer.clear(); int flvStereoOrMono = (m_channelCount == 2 ? FLV_STEREO : FLV_MONO); int flvSampleRate = FLV_SAMPLERATE_44100HZ; // default if (m_sampleRate == 22050.0) { flvSampleRate = FLV_SAMPLERATE_22050HZ; } int flags = 0; const int flags_size = 2; int ts = metadata.timestampDelta + m_ctsOffset ; // DLog("AAC: %06d", ts); auto output = m_output.lock(); RTMPMetadata_t outMeta(ts); if(inSize == 2 && !m_asc[0] && !m_asc[1]) { m_asc[0] = inBuffer[0]; m_asc[1] = inBuffer[1]; } if(output) { flags = FLV_CODECID_AAC | flvSampleRate | FLV_SAMPLESSIZE_16BIT | flvStereoOrMono; outBuffer.reserve(inSize + flags_size); put_byte(outBuffer, flags); put_byte(outBuffer, m_sentAudioConfig); if(!m_sentAudioConfig) { m_sentAudioConfig = true; put_buff(outBuffer, (uint8_t*)m_asc, sizeof(m_asc)); } else { put_buff(outBuffer, inBuffer, inSize); } outMeta.setData(ts, static_cast<int>(outBuffer.size()), RTMP_PT_AUDIO, kAudioChannelStreamId, false); output->pushBuffer(&outBuffer[0], outBuffer.size(), outMeta); } }
void AACPacketizer::pushBuffer(const uint8_t* const inBuffer, size_t inSize, IMetadata& metadata) { std::vector<uint8_t> & outBuffer = m_outbuffer; outBuffer.clear(); int flags = 0; const int flags_size = 2; int ts = metadata.timestampDelta; auto output = m_output.lock(); RTMPMetadata_t outMeta(metadata.timestampDelta); if(inSize == 2 && !m_asc[0] && !m_asc[1]) { m_asc[0] = inBuffer[0]; m_asc[1] = inBuffer[1]; } if(output) { flags = FLV_CODECID_AAC | FLV_SAMPLERATE_44100HZ | FLV_SAMPLESSIZE_16BIT | FLV_STEREO; outBuffer.reserve(inSize + flags_size); put_byte(outBuffer, flags); put_byte(outBuffer, m_sentAudioConfig); if(!m_sentAudioConfig) { m_sentAudioConfig = true; put_buff(outBuffer, (uint8_t*)m_asc, sizeof(m_asc)); } else { put_buff(outBuffer, inBuffer, inSize); m_audioTs += metadata.timestampDelta; } outMeta.setData(ts, static_cast<int>(outBuffer.size()), FLV_TAG_TYPE_AUDIO, kAudioChannelStreamId); 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; 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); } }