Skip to content

Commit

Permalink
rtc源支持丢264 b帧操作
Browse files Browse the repository at this point in the history
  • Loading branch information
cqm committed Dec 31, 2024
1 parent 4ddb88f commit 6bc529e
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 2 deletions.
140 changes: 140 additions & 0 deletions ext-codec/H264.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,146 @@ using namespace std;
using namespace toolkit;

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

static uint32_t janus_pp_h264_eg_decode(uint8_t *base, uint32_t *offset) {
uint32_t zeros = 0;
while (janus_pp_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 |= janus_pp_h264_eg_getbit(base, (*offset)++) << i;
}
}
return res - 1;
}

/* Helper to parse a SPS (only to get the video resolution) */
static void janus_pp_h264_parse_sps(char *buffer, int *width, int *height) {
/* Let's check if it's the right profile, first */
int index = 1;
int profile_idc = *(buffer + index);
if (profile_idc != 66) {
WarnL << "Profile is not baseline " << profile_idc;
}
/* Then let's skip 2 bytes and evaluate/skip the rest */
index += 3;
uint32_t offset = 0;
uint8_t *base = (uint8_t *)(buffer + index);
/* Skip seq_parameter_set_id */
janus_pp_h264_eg_decode(base, &offset);
if (profile_idc >= 100) {
/* Skip chroma_format_idc */
janus_pp_h264_eg_decode(base, &offset);
/* Skip bit_depth_luma_minus8 */
janus_pp_h264_eg_decode(base, &offset);
/* Skip bit_depth_chroma_minus8 */
janus_pp_h264_eg_decode(base, &offset);
/* Skip qpprime_y_zero_transform_bypass_flag */
janus_pp_h264_eg_getbit(base, offset++);
/* Skip seq_scaling_matrix_present_flag */
janus_pp_h264_eg_getbit(base, offset++);
}
/* Skip log2_max_frame_num_minus4 */
janus_pp_h264_eg_decode(base, &offset);
/* Evaluate pic_order_cnt_type */
int pic_order_cnt_type = janus_pp_h264_eg_decode(base, &offset);
if (pic_order_cnt_type == 0) {
/* Skip log2_max_pic_order_cnt_lsb_minus4 */
janus_pp_h264_eg_decode(base, &offset);
} else if (pic_order_cnt_type == 1) {
/* Skip delta_pic_order_always_zero_flag, offset_for_non_ref_pic,
* offset_for_top_to_bottom_field and num_ref_frames_in_pic_order_cnt_cycle */
janus_pp_h264_eg_getbit(base, offset++);
janus_pp_h264_eg_decode(base, &offset);
janus_pp_h264_eg_decode(base, &offset);
int num_ref_frames_in_pic_order_cnt_cycle = janus_pp_h264_eg_decode(base, &offset);
int i = 0;
for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
janus_pp_h264_eg_decode(base, &offset);
}
}
/* Skip max_num_ref_frames and gaps_in_frame_num_value_allowed_flag */
janus_pp_h264_eg_decode(base, &offset);
janus_pp_h264_eg_getbit(base, offset++);
/* We need the following three values */
int pic_width_in_mbs_minus1 = janus_pp_h264_eg_decode(base, &offset);
int pic_height_in_map_units_minus1 = janus_pp_h264_eg_decode(base, &offset);
int frame_mbs_only_flag = janus_pp_h264_eg_getbit(base, offset++);
if (!frame_mbs_only_flag) {
/* Skip mb_adaptive_frame_field_flag */
janus_pp_h264_eg_getbit(base, offset++);
}
/* Skip direct_8x8_inference_flag */
janus_pp_h264_eg_getbit(base, offset++);
/* We need the following value to evaluate offsets, if any */
int frame_cropping_flag = janus_pp_h264_eg_getbit(base, offset++);
int frame_crop_left_offset = 0, frame_crop_right_offset = 0, frame_crop_top_offset = 0, frame_crop_bottom_offset = 0;
if (frame_cropping_flag) {
frame_crop_left_offset = janus_pp_h264_eg_decode(base, &offset);
frame_crop_right_offset = janus_pp_h264_eg_decode(base, &offset);
frame_crop_top_offset = janus_pp_h264_eg_decode(base, &offset);
frame_crop_bottom_offset = janus_pp_h264_eg_decode(base, &offset);
}
/* Skip vui_parameters_present_flag */
janus_pp_h264_eg_getbit(base, offset++);

/* We skipped what we didn't care about and got what we wanted, compute width/height */
if (width)
*width = ((pic_width_in_mbs_minus1 + 1) * 16) - frame_crop_left_offset * 2 - frame_crop_right_offset * 2;
if (height)
*height = ((2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16) - (frame_crop_top_offset * 2) - (frame_crop_bottom_offset * 2);
}

enum SrsAvcSliceType {
SrsAvcSliceTypeP = 0,
SrsAvcSliceTypeB = 1,
SrsAvcSliceTypeI = 2,
SrsAvcSliceTypeSP = 3,
SrsAvcSliceTypeSI = 4,
SrsAvcSliceTypeP1 = 5,
SrsAvcSliceTypeB1 = 6,
SrsAvcSliceTypeI1 = 7,
SrsAvcSliceTypeSP1 = 8,
SrsAvcSliceTypeSI1 = 9,
};

bool h264_is_bframe(uint8_t *buffer, int size) {
uint8_t nalTye = buffer[0] & 0x1F;
if (nalTye = 5 || nalTye == 1) {
return false;
}
buffer++;
uint32_t offset = 0;
/* i_first_mb */
janus_pp_h264_eg_decode(buffer, &offset);
/* picture type */
int frame_type = janus_pp_h264_eg_decode(buffer, &offset);
switch(frame_type)
{
case 0: case 5: // P
//nal->Frametype = FRAME_P;
break;
case 1: case 6: // B
return true;
break;
case 3: case 8: // SP
//nal->Frametype = FRAME_P;
break;
case 2: case 7: // I
//nal->Frametype = FRAME_I;
break;
case 4: case 9: // SI
//nal->Frametype = FRAME_I;
break;
}
return false;
}

static bool getAVCInfo(const char *sps, size_t sps_len, int &iVideoWidth, int &iVideoHeight, float &iVideoFps) {
if (sps_len < 4) {
Expand Down
1 change: 1 addition & 0 deletions ext-codec/H264.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ 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);
bool h264_is_bframe(uint8_t *buffer, int size);

template<typename Parent>
class H264FrameHelper : public Parent{
Expand Down
15 changes: 13 additions & 2 deletions webrtc/RtcMediaSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "Rtsp/RtspMediaSourceMuxer.h"
#include "Rtsp/RtspMediaSourceImp.h"
namespace mediakit {

extern bool h264_is_bframe(uint8_t *buffer, int size);
class RtcMediaSourceImp : public RtspMediaSourceImp {
public:
using Ptr = std::shared_ptr<RtcMediaSourceImp>;
Expand Down Expand Up @@ -51,7 +51,18 @@ class RtcMediaSourceMuxer : public RtspMediaSourceMuxer {
_trans->delDelegate(this);
}
}
protected:

bool inputFrame(const Frame::Ptr &frame) override {
// skip b-frame for webrtc
if (frame->getCodecId() == CodecH264) {
if (h264_is_bframe((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

0 comments on commit 6bc529e

Please sign in to comment.