[core,mod_av,unit-tests] Make transition to core packetizer

This commit is contained in:
Jakub Karolczyk 2023-07-10 10:31:09 +00:00
parent 48e1812e29
commit 930341ba86
4 changed files with 65 additions and 93 deletions

View File

@ -399,6 +399,7 @@ typedef struct h264_codec_context_s {
enum AVCodecID av_codec_id;
uint16_t last_seq; // last received frame->seq
int hw_encoder;
switch_packetizer_t *packetizer;
} h264_codec_context_t;
#ifndef AV_INPUT_BUFFER_PADDING_SIZE
@ -1088,64 +1089,6 @@ static switch_status_t consume_h263p_bitstream(h264_codec_context_t *context, sw
return SWITCH_STATUS_MORE_DATA;
}
static switch_status_t consume_h264_bitstream(h264_codec_context_t *context, switch_frame_t *frame)
{
AVPacket *pkt = &context->encoder_avpacket;
our_h264_nalu_t *nalu = &context->nalus[context->nalu_current_index];
uint8_t nalu_hdr = *(uint8_t *)(nalu->start);
uint8_t nalu_type = nalu_hdr & 0x1f;
uint8_t nri = nalu_hdr & 0x60;
int left = nalu->len - (nalu->eat - nalu->start);
uint8_t *p = frame->data;
uint8_t start = nalu->start == nalu->eat ? 0x80 : 0;
int n = nalu->len / SLICE_SIZE;
int slice_size = nalu->len / (n + 1) + 1 + 2;
if (nalu->len <= SLICE_SIZE) {
memcpy(frame->data, nalu->start, nalu->len);
frame->datalen = nalu->len;
context->nalu_current_index++;
if (context->nalus[context->nalu_current_index].len) {
frame->m = 0;
return SWITCH_STATUS_MORE_DATA;
}
if (pkt->size > 0) av_packet_unref(pkt);
switch_clear_flag(frame, SFF_CNG);
frame->m = 1;
return SWITCH_STATUS_SUCCESS;
}
if (left <= (slice_size - 2)) {
p[0] = nri | 28; // FU-A
p[1] = 0x40 | nalu_type;
memcpy(p+2, nalu->eat, left);
nalu->eat += left;
frame->datalen = left + 2;
context->nalu_current_index++;
if (!context->nalus[context->nalu_current_index].len) {
if (pkt->size > 0) av_packet_unref(pkt);
frame->m = 1;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_MORE_DATA;
}
p[0] = nri | 28; // FU-A
p[1] = start | nalu_type;
if (start) nalu->eat++;
memcpy(p+2, nalu->eat, slice_size - 2);
nalu->eat += (slice_size - 2);
frame->datalen = slice_size;
frame->m = 0;
return SWITCH_STATUS_MORE_DATA;
}
static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_t *frame)
{
AVPacket *pkt = &context->encoder_avpacket;
@ -1154,8 +1097,12 @@ static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_
if (!nalu->len) {
frame->datalen = 0;
frame->m = 0;
if (pkt->size > 0) av_packet_unref(pkt);
if (pkt->size > 0) {
av_packet_unref(pkt);
}
context->nalu_current_index = 0;
return SWITCH_STATUS_NOTFOUND;
}
@ -1167,7 +1114,9 @@ static switch_status_t consume_nalu(h264_codec_context_t *context, switch_frame_
return consume_h263p_bitstream(context, frame);
}
return consume_h264_bitstream(context, frame);
switch_assert(0);
return SWITCH_STATUS_FALSE;
}
static void set_h264_private_data(h264_codec_context_t *context, avcodec_profile_t *profile)
@ -1436,6 +1385,14 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
}
}
switch (context->av_codec_id) {
case AV_CODEC_ID_H264:
context->packetizer = switch_packetizer_create(SPT_H264_BITSTREAM, SLICE_SIZE);
break;
default:
break;
}
switch_buffer_create_dynamic(&(context->nalu_buffer), H264_NALU_BUFFER_SIZE, H264_NALU_BUFFER_SIZE * 8, 0);
codec->private_info = context;
@ -1480,6 +1437,16 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
}
if (frame->flags & SFF_SAME_IMAGE) {
if (context->packetizer) {
switch_status_t status = switch_packetizer_read(context->packetizer, frame);
if (status == SWITCH_STATUS_SUCCESS && pkt->size > 0) {
av_packet_unref(pkt);
}
return status;
}
// read from nalu buffer
return consume_nalu(context, frame);
}
@ -1511,7 +1478,9 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
}
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(pkt);
GCC_DIAG_ON(deprecated-declarations)
pkt->data = NULL; // packet data will be allocated by the encoder
pkt->size = 0;
@ -1596,8 +1565,7 @@ GCC_DIAG_ON(deprecated-declarations)
// process:
if (*got_output) {
const uint8_t *p = pkt->data;
int i = 0;
switch_status_t status = SWITCH_STATUS_SUCCESS;
*got_output = 0;
@ -1626,38 +1594,22 @@ GCC_DIAG_ON(deprecated-declarations)
"Encoded frame %" SWITCH_INT64_T_FMT " (size=%5d) nalu_type=0x%x %d\n",
context->pts, pkt->size, *((uint8_t *)pkt->data +4), *got_output);
}
/* split into nalus */
memset(context->nalus, 0, sizeof(context->nalus));
while ((p = fs_avc_find_startcode(p, pkt->data+pkt->size)) < (pkt->data + pkt->size)) {
if (!context->nalus[i].start) {
while (!(*p++)) ; /* eat the sync bytes, what ever 0 0 1 or 0 0 0 1 */
context->nalus[i].start = p;
context->nalus[i].eat = p;
status = switch_packetizer_feed(context->packetizer, pkt->data, pkt->size);
if (status != SWITCH_STATUS_SUCCESS) {
if (pkt->size > 0) {
av_packet_unref(pkt);
}
if ((*p & 0x1f) == 7) { // Got Keyframe
// prevent to generate key frame too frequently
context->last_keyframe_request = switch_time_now();
if (mod_av_globals.debug) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "KEY FRAME GENERATED\n");
}
}
} else {
context->nalus[i].len = p - context->nalus[i].start;
while (!(*p++)) ; /* eat the sync bytes, what ever 0 0 1 or 0 0 0 1 */
i++;
context->nalus[i].start = p;
context->nalus[i].eat = p;
}
if (i >= MAX_NALUS - 2) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "TOO MANY SLICES!\n");
break;
}
return status;
}
context->nalus[i].len = p - context->nalus[i].start;
context->nalu_current_index = 0;
return consume_nalu(context, frame);
status = switch_packetizer_read(context->packetizer, frame);
if (status == SWITCH_STATUS_SUCCESS && pkt->size > 0) {
av_packet_unref(pkt);
}
return status;
}
error:
@ -1708,7 +1660,9 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec, switch_frame_t
int decoded_len;
if (size > 0) {
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(&pkt);
GCC_DIAG_ON(deprecated-declarations)
switch_buffer_zero_fill(context->nalu_buffer, AV_INPUT_BUFFER_PADDING_SIZE);
switch_buffer_peek_zerocopy(context->nalu_buffer, (const void **)&pkt.data);
pkt.size = size;
@ -1825,6 +1779,10 @@ static switch_status_t switch_h264_destroy(switch_codec_t *codec)
av_free(context->encoder_ctx);
}
if (context->packetizer) {
switch_packetizer_close(&context->packetizer);
}
if (context->encoder_avframe) {
av_frame_free(&context->encoder_avframe);
}

View File

@ -877,7 +877,9 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
context->eh.in_callback = 1;
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(&pkt);
GCC_DIAG_ON(deprecated-declarations)
if (context->eh.video_st->frame) {
ret = av_frame_make_writable(context->eh.video_st->frame);
@ -971,7 +973,9 @@ GCC_DIAG_ON(deprecated-declarations)
int got_packet = 0;
int ret = 0;
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(&pkt);
GCC_DIAG_ON(deprecated-declarations)
GCC_DIAG_OFF(deprecated-declarations)
ret = avcodec_encode_video2(context->eh.video_st->st->codec, &pkt, NULL, &got_packet);
@ -1427,7 +1431,9 @@ GCC_DIAG_ON(deprecated-declarations)
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(&pkt);
GCC_DIAG_ON(deprecated-declarations)
pkt.data = NULL;
pkt.size = 0;
@ -1464,7 +1470,9 @@ GCC_DIAG_ON(deprecated-declarations)
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "size = %u %x %x %x %x %x %x\n", pkt.size, *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5));
}
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(new_pkt);
GCC_DIAG_ON(deprecated-declarations)
av_packet_ref(new_pkt, &pkt);
status = switch_queue_push(context->video_pkt_queue, new_pkt);
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "size = %4u flag=%x pts=%" SWITCH_INT64_T_FMT " dts=%" SWITCH_INT64_T_FMT "\n", pkt.size, pkt.flags, pkt.pts, pkt.dts);
@ -2102,8 +2110,10 @@ GCC_DIAG_ON(deprecated-declarations)
int j = 0, ret = -1, audio_stream_count = 1;
AVFrame *use_frame = NULL;
GCC_DIAG_OFF(deprecated-declarations)
av_init_packet(&pkt[0]);
av_init_packet(&pkt[1]);
GCC_DIAG_ON(deprecated-declarations)
if (context->audio_st[1].active) {
switch_size_t len = 0;

View File

@ -265,7 +265,7 @@ SWITCH_DECLARE(switch_status_t) switch_packetizer_feed(switch_packetizer_t *pack
context->nalus[i].eat = p;
} else {
context->nalus[i].len = p - context->nalus[i].start;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "#%d %x len=%u\n", i, *context->nalus[i].start, context->nalus[i].len);
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "#%d %x len=%u\n", i, *context->nalus[i].start, context->nalus[i].len);
while (!(*p++)) ; /* eat the sync bytes, what ever 0 0 1 or 0 0 0 1 */
i++;
context->nalus[i].start = p;
@ -307,8 +307,8 @@ SWITCH_DECLARE(switch_status_t) switch_packetizer_read(switch_packetizer_t *pack
nri = nalu_hdr & 0x60;
if (real_slice_size > slice_size) real_slice_size = slice_size;
if (frame->buflen < slice_size) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "frame buffer too small %u < %u\n", frame->buflen, slice_size);
if (frame->datalen < slice_size) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "frame buffer too small %u < %u\n", frame->datalen, slice_size);
return SWITCH_STATUS_FALSE;
}

View File

@ -52,6 +52,7 @@ FST_CORE_BEGIN("conf")
frame.data = data;
frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
frame.datalen = SWITCH_RECOMMENDED_BUFFER_SIZE;
switch_set_flag(&frame, SFF_ENCODED);
status = switch_packetizer_feed(packetizer, h264data, sizeof(h264data));
@ -94,6 +95,7 @@ FST_CORE_BEGIN("conf")
frame.data = data;
frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
frame.datalen = SWITCH_RECOMMENDED_BUFFER_SIZE;
switch_set_flag(&frame, SFF_ENCODED);
status = switch_packetizer_feed(packetizer, h264data, sizeof(h264data));
@ -138,6 +140,7 @@ FST_CORE_BEGIN("conf")
// 1 fps 3 bytes 1pps 3 bytes
frame.data = data;
frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
frame.datalen = SWITCH_RECOMMENDED_BUFFER_SIZE;
switch_set_flag(&frame, SFF_ENCODED);
status = switch_packetizer_feed_extradata(packetizer, extradata, sizeof(extradata));
@ -210,6 +213,7 @@ FST_CORE_BEGIN("conf")
frame.data = data;
frame.buflen = SWITCH_RECOMMENDED_BUFFER_SIZE;
frame.datalen = SWITCH_RECOMMENDED_BUFFER_SIZE;
switch_set_flag(&frame, SFF_ENCODED);
status = switch_packetizer_feed(packetizer, h264data, sizeof(h264data));