Skip to content

Commit

Permalink
rtc源支持丢264 b帧操作
Browse files Browse the repository at this point in the history
  • Loading branch information
cqm authored and mtdxc committed Jan 1, 2025
1 parent 4ddb88f commit f28fdf5
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 1 deletion.
52 changes: 52 additions & 0 deletions ext-codec/H264.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,58 @@ using namespace std;
using namespace toolkit;

namespace mediakit {
/* Helpers to decode Exp-Golomb */
static uint32_t h264_eg_getbit(uint8_t *base, uint32_t offset) {
return ((*(base + (offset >> 0x3))) >> (0x7 - (offset & 0x7))) & 0x1;
}

static uint32_t h264_eg_decode(uint8_t *base, uint32_t *offset) {
uint32_t zeros = 0;
while (h264_eg_getbit(base, (*offset)++) == 0)
zeros++;
uint32_t res = 1 << zeros;
if (zeros > 0) {
int32_t i = 0;
for (i = zeros - 1; i >= 0; i--) {
res |= h264_eg_getbit(base, (*offset)++) << i;
}
}
return res - 1;
}

// @see https://blog.csdn.net/dittychen/article/details/55509718
int h264_frameType(uint8_t *buffer, int size) {
uint8_t nalTye = buffer[0] & 0x1F;
if (nalTye != 1 && nalTye != 5) {
return 0;
}
buffer++;
int frametype = 0;
uint32_t offset = 0;
/* i_first_mb */
h264_eg_decode(buffer, &offset);
/* picture type */
int frame_type = h264_eg_decode(buffer, &offset);
switch(frame_type)
{
case 0: case 5: // P
frametype = FRAME_P;
break;
case 1: case 6: // B
frametype = FRAME_B;
break;
case 3: case 8: // SP
frametype = FRAME_P;
break;
case 2: case 7: // I
frametype = FRAME_I;
break;
case 4: case 9: // SI
frametype = FRAME_I;
break;
}
return frametype;
}

static bool getAVCInfo(const char *sps, size_t sps_len, int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
if (sps_len < 4) {
Expand Down
9 changes: 9 additions & 0 deletions ext-codec/H264.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ namespace mediakit{

void splitH264(const char *ptr, size_t len, size_t prefix, const std::function<void(const char *, size_t, size_t)> &cb);
size_t prefixSize(const char *ptr, size_t len);
enum H264FrameTye { FRAME_I, FRAME_P, FRAME_B };
int h264_frameType(uint8_t *data, int size);

template<typename Parent>
class H264FrameHelper : public Parent{
Expand Down Expand Up @@ -72,6 +74,13 @@ class H264FrameHelper : public Parent{
// // In the case of multiple slices, first_mb_in_slice indicates the start of a frame
return type >= NAL_B_P && type <= NAL_IDR && (nal_ptr[1] & 0x80);
}

bool bframe() const {
auto nal_ptr = (uint8_t *)this->data() + this->prefixSize();
if (H264_TYPE(*nal_ptr) != NAL_B_P)
return false;
return FRAME_B == h264_frameType(nal_ptr, this->size() - this->prefixSize());
}
};

/**
Expand Down
16 changes: 15 additions & 1 deletion webrtc/RtcMediaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "Rtsp/RtspMediaSourceMuxer.h"
#include "Rtsp/RtspMediaSourceImp.h"
#include "webrtc/WebRtcTransport.h"
#include "ext-codec/H264.h"
namespace mediakit {

class RtcMediaSourceImp : public RtspMediaSourceImp {
Expand Down Expand Up @@ -51,7 +53,19 @@ class RtcMediaSourceMuxer : public RtspMediaSourceMuxer {
_trans->delDelegate(this);
}
}
protected:

bool inputFrame(const Frame::Ptr &frame) override {
// skip b-frame for webrtc
GET_CONFIG(int, dropBFrame, Rtc::kDrop264BFrame);
if (dropBFrame && frame->getCodecId() == CodecH264) {
if (FRAME_B == h264_frameType((uint8_t *)frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize())) {
DebugL << "skipFrame " << frame->size() << " tsp:" << frame->pts() << "," << frame->dts();
return true;
}
}
return RtspMediaSourceMuxer::inputFrame(frame);
}
protected:
Track::Ptr _trans;
};

Expand Down
2 changes: 2 additions & 0 deletions webrtc/WebRtcTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const string kMinBitrate = RTC_FIELD "min_bitrate";
// 数据通道设置 [AUTO-TRANSLATED:2dc48bc3]
// Data channel setting
const string kDataChannelEcho = RTC_FIELD "datachannel_echo";
const string kDrop264BFrame = RTC_FIELD "drop_h264_bframe";

static onceToken token([]() {
mINI::Instance()[kTimeOutSec] = 15;
Expand All @@ -76,6 +77,7 @@ static onceToken token([]() {
mINI::Instance()[kMaxBitrate] = 0;
mINI::Instance()[kMinBitrate] = 0;

mINI::Instance()[kDrop264BFrame] = true;
mINI::Instance()[kDataChannelEcho] = true;
});

Expand Down
1 change: 1 addition & 0 deletions webrtc/WebRtcTransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ namespace Rtc {
extern const std::string kPort;
extern const std::string kTcpPort;
extern const std::string kTimeOutSec;
extern const std::string kDrop264BFrame;
}//namespace RTC

class WebRtcInterface {
Expand Down

0 comments on commit f28fdf5

Please sign in to comment.