mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-07-23 12:42:02 +00:00
FS-7500: another refactoring pass, temp code still in place, WORK IN PROGRESS
This commit is contained in:
committed by
Michael Jerris
parent
258dacc742
commit
0cd5658caa
@@ -39,7 +39,7 @@
|
||||
#include "codec_api.h"
|
||||
//#include "inc/logging.h" // for debug
|
||||
|
||||
#define FPS 15.0f // frame rate
|
||||
#define FPS 20.0f // frame rate
|
||||
#define H264_NALU_BUFFER_SIZE 65536
|
||||
#define MAX_NALUS 100
|
||||
#define SLICE_SIZE 1200 //NALU Slice Size
|
||||
@@ -66,15 +66,16 @@ typedef struct h264_codec_context_s {
|
||||
switch_image_t *img;
|
||||
int got_sps;
|
||||
int64_t pts;
|
||||
int need_key_frame;
|
||||
switch_size_t last_received_timestamp;
|
||||
switch_bool_t last_received_complete_picture;
|
||||
} h264_codec_context_t;
|
||||
|
||||
int FillSpecificParameters(SEncParamExt& param) {
|
||||
/* Test for temporal, spatial, SNR scalability */
|
||||
param.iPicWidth = 352; // width of picture in samples
|
||||
param.iPicHeight = 288; // height of picture in samples
|
||||
param.iTargetBitrate = 384000; // target bitrate desired
|
||||
param.iPicWidth = 1280; // width of picture in samples
|
||||
param.iPicHeight = 720; // height of picture in samples
|
||||
param.iTargetBitrate = 1280 * 720 * 8; // target bitrate desired
|
||||
param.iRCMode = RC_QUALITY_MODE; // rc mode control
|
||||
param.uiMaxNalSize = SLICE_SIZE * 20;
|
||||
param.iTemporalLayerNum = 1; // layer number at temporal level
|
||||
@@ -91,11 +92,11 @@ int FillSpecificParameters(SEncParamExt& param) {
|
||||
param.bPrefixNalAddingCtrl = 0;
|
||||
|
||||
int iIndexLayer = 0;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoWidth = 352;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoHeight = 288;
|
||||
param.sSpatialLayers[iIndexLayer].fFrameRate = 15.0f;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoWidth = 1280;
|
||||
param.sSpatialLayers[iIndexLayer].iVideoHeight = 720;
|
||||
param.sSpatialLayers[iIndexLayer].fFrameRate = (double) (FPS * 1.0f);
|
||||
// param.sSpatialLayers[iIndexLayer].iQualityLayerNum = 1;
|
||||
param.sSpatialLayers[iIndexLayer].iSpatialBitrate = 384000;
|
||||
param.sSpatialLayers[iIndexLayer].iSpatialBitrate = 1280 * 720 * 8;
|
||||
|
||||
#ifdef MT_ENABLED
|
||||
param.sSpatialLayers[iIndexLayer].sSliceCfg.uiSliceMode = SM_DYN_SLICE;
|
||||
@@ -137,27 +138,21 @@ static switch_size_t buffer_h264_nalu(h264_codec_context_t *context, switch_fram
|
||||
switch_buffer_t *buffer = context->nalu_buffer;
|
||||
switch_size_t size = 0;
|
||||
|
||||
if (!frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No frame in codec!!\n");
|
||||
return size;
|
||||
}
|
||||
|
||||
switch_assert(frame);
|
||||
|
||||
nalu_idc = (nalu_hdr & 0x60) >> 5;
|
||||
nalu_type = nalu_hdr & 0x1f;
|
||||
|
||||
if (!context->got_sps && nalu_type != 7) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting SPS/PPS\n");
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
return size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!context->got_sps) context->got_sps = 1;
|
||||
|
||||
size = switch_buffer_write(buffer, sync_bytes, sizeof(sync_bytes));
|
||||
if (size == 0 ) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer Memory Error!\n");
|
||||
|
||||
size = switch_buffer_write(buffer, frame->data, frame->datalen);
|
||||
if (size == 0 ) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Buffer Memory Error!\n");
|
||||
|
||||
|
||||
#ifdef DEBUG_H264
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "ts: %ld len: %4d %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x mark=%d size=%d\n",
|
||||
@@ -173,13 +168,13 @@ static switch_size_t buffer_h264_nalu(h264_codec_context_t *context, switch_fram
|
||||
return size;
|
||||
}
|
||||
|
||||
static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uint32_t *len, uint32_t *flag)
|
||||
static switch_status_t nalu_slice(h264_codec_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
int nalu_len;
|
||||
uint8_t *buffer;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
*flag &= ~SFF_MARKER;
|
||||
frame->m = SWITCH_FALSE;
|
||||
|
||||
if (context->cur_nalu_index >= context->bit_stream_info.sLayerInfo[context->cur_layer].iNalCount) {
|
||||
context->cur_nalu_index = 0;
|
||||
@@ -198,8 +193,8 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
||||
|
||||
if (context->last_frame_type == videoFrameTypeSkip ||
|
||||
context->cur_layer >= context->bit_stream_info.iLayerNum) {
|
||||
*len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = SWITCH_TRUE;
|
||||
context->cur_layer = 0;
|
||||
context->cur_nalu_index = 0;
|
||||
return status;
|
||||
@@ -225,12 +220,12 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
||||
|
||||
// if (nalu_type == 7) switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Got SPS\n");
|
||||
|
||||
memcpy(data, (buffer + context->last_nalu_data_pos), nalu_len);
|
||||
*len = nalu_len;
|
||||
memcpy(frame->data, (buffer + context->last_nalu_data_pos), nalu_len);
|
||||
frame->datalen = nalu_len;
|
||||
// *flag |= (nalu_type == 6 || nalu_type == 7 || nalu_type == 8 || (nalu_type == 0xe && context->last_nalu_type == 8)) ? 0 : SFF_MARKER;
|
||||
if ((context->cur_nalu_index == context->bit_stream_info.sLayerInfo[context->cur_layer].iNalCount - 1) &&
|
||||
(context->cur_layer == context->bit_stream_info.iLayerNum - 1)) {
|
||||
*flag |= SFF_MARKER;
|
||||
frame->m = SWITCH_TRUE;
|
||||
} else {
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
@@ -240,7 +235,7 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
||||
goto end;
|
||||
} else {
|
||||
int left = nalu_len;
|
||||
uint8_t *p = (uint8_t *)data;
|
||||
uint8_t *p = (uint8_t *) frame->data;
|
||||
|
||||
if (context->nalu_eat) {
|
||||
left = nalu_len + 4 - context->nalu_eat;
|
||||
@@ -267,7 +262,7 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
||||
memcpy(p + 2, buffer + context->last_nalu_data_pos, SLICE_SIZE - 2);
|
||||
context->last_nalu_data_pos += (SLICE_SIZE - 2);
|
||||
context->nalu_eat += (SLICE_SIZE - 2);
|
||||
*len = SLICE_SIZE;
|
||||
frame->datalen = SLICE_SIZE;
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
goto end;
|
||||
} else {
|
||||
@@ -275,8 +270,8 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, void *data, uin
|
||||
p[1] = 0x40 | context->last_nalu_type;
|
||||
memcpy(p + 2, buffer + context->last_nalu_data_pos, left);
|
||||
context->last_nalu_data_pos += left;
|
||||
*len = left + 2;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = left + 2;
|
||||
frame->m = SWITCH_TRUE;
|
||||
context->nalu_eat = 0;
|
||||
context->cur_nalu_index++;
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
@@ -361,6 +356,7 @@ static switch_status_t init_encoder(h264_codec_context_t *context, uint32_t widt
|
||||
|
||||
context->encoder_params.iPicWidth = width;
|
||||
context->encoder_params.iPicHeight = height;
|
||||
|
||||
for (int i=0; i<context->encoder_params.iSpatialLayerNum; i++) {
|
||||
context->encoder_params.sSpatialLayers[i].iVideoWidth = width;
|
||||
context->encoder_params.sSpatialLayers[i].iVideoHeight = height;
|
||||
@@ -371,14 +367,12 @@ static switch_status_t init_encoder(h264_codec_context_t *context, uint32_t widt
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Encoder Init Error\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
context->encoder_initialized = SWITCH_TRUE;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
|
||||
int width = 0;
|
||||
@@ -387,17 +381,24 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
||||
SSourcePicture* pic = NULL;
|
||||
long result;
|
||||
|
||||
if (*flag & SFF_WAIT_KEY_FRAME) {
|
||||
if (context->need_key_frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "H264 KEYFRAME GENERATED\n");
|
||||
context->encoder->ForceIntraFrame(1);
|
||||
context->need_key_frame = 0;
|
||||
}
|
||||
|
||||
if (img == NULL) {
|
||||
return nalu_slice(context, encoded_data, encoded_data_len, flag);
|
||||
if (frame->flags & SFF_SAME_IMAGE) {
|
||||
return nalu_slice(context, frame);
|
||||
}
|
||||
|
||||
//d_w and d_h are corrupt
|
||||
width = img->w;
|
||||
height = img->h;
|
||||
|
||||
if (frame->img->d_h > 1) {
|
||||
width = frame->img->d_w;
|
||||
height = frame->img->d_h;
|
||||
} else {
|
||||
width = frame->img->w;
|
||||
height = frame->img->h;
|
||||
}
|
||||
|
||||
//switch_assert(width > 0 && (width % 2 == 0));
|
||||
//switch_assert(height > 0 && (height % 2 == 0));
|
||||
@@ -419,12 +420,12 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
||||
pic->iColorFormat = videoFormatI420;
|
||||
pic->iPicHeight = height;
|
||||
pic->iPicWidth = width;
|
||||
pic->iStride[0] = img->stride[0];
|
||||
pic->iStride[1] = img->stride[1]; // = img->stride[2];
|
||||
pic->iStride[0] = frame->img->stride[0];
|
||||
pic->iStride[1] = frame->img->stride[1]; // = frame->img->stride[2];
|
||||
|
||||
pic->pData[0] = img->planes[0];
|
||||
pic->pData[1] = img->planes[1];
|
||||
pic->pData[2] = img->planes[2];
|
||||
pic->pData[0] = frame->img->planes[0];
|
||||
pic->pData[1] = frame->img->planes[1];
|
||||
pic->pData[2] = frame->img->planes[2];
|
||||
|
||||
result = (EVideoFrameType)context->encoder->EncodeFrame(pic, &context->bit_stream_info);
|
||||
if (result != cmResultSuccess ) {
|
||||
@@ -436,45 +437,48 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
|
||||
context->cur_nalu_index = 0;
|
||||
context->last_nalu_data_pos = 0;
|
||||
|
||||
if(pic){
|
||||
if (pic){
|
||||
delete pic;
|
||||
pic = NULL;
|
||||
}
|
||||
return nalu_slice(context, encoded_data, encoded_data_len, flag);
|
||||
|
||||
return nalu_slice(context, frame);
|
||||
|
||||
error:
|
||||
|
||||
if(pic){
|
||||
delete pic;
|
||||
pic = NULL;
|
||||
}
|
||||
|
||||
*encoded_data_len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = SWITCH_TRUE;
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
static switch_status_t switch_h264_decode(switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_h264_decode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
|
||||
switch_size_t size = 0;
|
||||
uint32_t error_code;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %u mark:%d\n", frame->datalen, ntohl(frame->timestamp), frame->m);
|
||||
|
||||
if (context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
if (0 && context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
(!frame->m) && (!context->last_received_complete_picture)) {
|
||||
// possible packet loss
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Packet Loss, skip privousely received packets\n");
|
||||
switch_buffer_zero(context->nalu_buffer);
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
context->last_received_timestamp = frame->timestamp;
|
||||
context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;
|
||||
|
||||
size = buffer_h264_nalu(context, frame);
|
||||
printf("READ buf:%ld got_key:%d st:%d m:%d\n", size, context->got_sps, status, frame->m);
|
||||
|
||||
|
||||
if (frame->m && size) {
|
||||
int got_picture = 0;
|
||||
@@ -485,6 +489,11 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec,
|
||||
SBufferInfo dest_buffer_info;
|
||||
switch_buffer_peek_zerocopy(context->nalu_buffer, &nalu);
|
||||
uint8_t* pData[3] = { 0 };
|
||||
|
||||
|
||||
frame->m = SWITCH_FALSE;
|
||||
frame->flags = 0;
|
||||
|
||||
|
||||
pData[0] = NULL;
|
||||
pData[1] = NULL;
|
||||
@@ -515,22 +524,40 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec,
|
||||
context->img->stride[1] = dest_buffer_info.UsrData.sSystemBuffer.iStride[1];
|
||||
context->img->stride[2] = dest_buffer_info.UsrData.sSystemBuffer.iStride[1];
|
||||
|
||||
*img = context->img;
|
||||
frame->img = context->img;
|
||||
// TODO: keep going and see if more picture available
|
||||
// pDecoder->DecodeFrame (NULL, 0, pData, &sDstBufInfo);
|
||||
} else {
|
||||
if (error_code) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Decode error: 0x%x\n", error_code);
|
||||
context->got_sps = 0;
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
}
|
||||
|
||||
switch_buffer_zero(context->nalu_buffer);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
status = SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (size == 0) {
|
||||
status == SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
||||
if (status == SWITCH_STATUS_RESTART) {
|
||||
context->got_sps = 0;
|
||||
switch_buffer_zero(context->nalu_buffer);
|
||||
}
|
||||
|
||||
if (!context->got_sps) {
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
}
|
||||
|
||||
if (!frame->img) {
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static switch_status_t switch_h264_control(switch_codec_t *codec,
|
||||
@@ -540,6 +567,18 @@ static switch_status_t switch_h264_control(switch_codec_t *codec,
|
||||
switch_codec_control_type_t *rtype,
|
||||
void **ret_data) {
|
||||
|
||||
|
||||
|
||||
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
|
||||
|
||||
switch(cmd) {
|
||||
case SCC_VIDEO_REFRESH:
|
||||
context->need_key_frame = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <vpx/vp8dx.h>
|
||||
#include <vpx/vp8.h>
|
||||
|
||||
#define FPS 15
|
||||
#define FPS 20
|
||||
#define SLICE_SIZE 1200
|
||||
|
||||
SWITCH_MODULE_LOAD_FUNCTION(mod_vpx_load);
|
||||
@@ -84,6 +84,24 @@ static switch_status_t init_codec(switch_codec_t *codec)
|
||||
vpx_context_t *context = (vpx_context_t *)codec->private_info;
|
||||
vpx_codec_enc_cfg_t *config = &context->config;
|
||||
|
||||
if (!context->codec_settings.video.width) {
|
||||
context->codec_settings.video.width = 1280;
|
||||
}
|
||||
|
||||
if (!context->codec_settings.video.height) {
|
||||
context->codec_settings.video.height = 720;
|
||||
}
|
||||
|
||||
if (context->codec_settings.video.bandwidth) {
|
||||
context->bandwidth = context->codec_settings.video.bandwidth;
|
||||
} else {
|
||||
context->bandwidth = context->codec_settings.video.width * context->codec_settings.video.height * 8;
|
||||
}
|
||||
|
||||
if (context->bandwidth > 1250000) {
|
||||
context->bandwidth = 1250000;
|
||||
}
|
||||
|
||||
// settings
|
||||
config->g_profile = 1;
|
||||
config->g_w = context->codec_settings.video.width;
|
||||
@@ -93,7 +111,8 @@ static switch_status_t init_codec(switch_codec_t *codec)
|
||||
config->g_timebase.den = 1000;
|
||||
config->g_error_resilient = VPX_ERROR_RESILIENT_PARTITIONS;
|
||||
config->g_lag_in_frames = 0; // 0- no frame lagging
|
||||
config->g_threads = 1;
|
||||
config->g_threads = (switch_core_cpu_count() > 1) ? 2 : 1;
|
||||
|
||||
// rate control settings
|
||||
config->rc_dropframe_thresh = 0;
|
||||
config->rc_end_usage = VPX_CBR;
|
||||
@@ -198,6 +217,8 @@ static switch_status_t init_codec(switch_codec_t *codec)
|
||||
vpx_codec_control(&context->decoder, VP8_SET_POSTPROC, &ppcfg);
|
||||
|
||||
switch_buffer_create_dynamic(&context->vpx_packet_buffer, 512, 512, 1024000);
|
||||
|
||||
printf("WTF CREATE ??? %p\n", (void *)context->vpx_packet_buffer);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -274,11 +295,11 @@ static switch_status_t switch_vpx_init(switch_codec_t *codec, switch_codec_flag_
|
||||
+-+-+-+-+-+-+-+-+
|
||||
*/
|
||||
|
||||
static switch_status_t consume_partition(vpx_context_t *context, void *data, uint32_t *len, uint32_t *flag)
|
||||
static switch_status_t consume_partition(vpx_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
if (!context->pkt) context->pkt = vpx_codec_get_cx_data(&context->encoder, &context->iter);
|
||||
|
||||
*flag &= ~SFF_MARKER;
|
||||
frame->m = 0;
|
||||
|
||||
if (context->pkt) {
|
||||
// if (context->pkt->kind == VPX_CODEC_CX_FRAME_PKT && (context->pkt->data.frame.flags & VPX_FRAME_IS_KEY) && context->pkt_pos == 0) {
|
||||
@@ -290,8 +311,8 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
|
||||
}
|
||||
|
||||
if (!context->pkt || context->pkt_pos >= context->pkt->data.frame.sz - 1 || context->pkt->kind != VPX_CODEC_CX_FRAME_PKT) {
|
||||
*len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = 1;
|
||||
context->pkt_pos = 0;
|
||||
context->pkt = NULL;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
@@ -300,24 +321,24 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
|
||||
if (context->pkt->data.frame.sz < SLICE_SIZE) {
|
||||
uint8_t hdr = 0x10;
|
||||
|
||||
memcpy(data, &hdr, 1);
|
||||
memcpy((uint8_t *)data + 1, context->pkt->data.frame.buf, context->pkt->data.frame.sz);
|
||||
*len = context->pkt->data.frame.sz + 1;
|
||||
*flag |= SFF_MARKER;
|
||||
memcpy(frame->data, &hdr, 1);
|
||||
memcpy((uint8_t *)frame->data + 1, context->pkt->data.frame.buf, context->pkt->data.frame.sz);
|
||||
frame->datalen = context->pkt->data.frame.sz + 1;
|
||||
frame->m = 1;
|
||||
context->pkt = NULL;
|
||||
context->pkt_pos = 0;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
int left = context->pkt->data.frame.sz - context->pkt_pos;
|
||||
uint8_t *p = data;
|
||||
uint8_t *p = frame->data;
|
||||
|
||||
if (left < SLICE_SIZE) {
|
||||
p[0] = 0;
|
||||
memcpy(p+1, (uint8_t *)context->pkt->data.frame.buf + context->pkt_pos, left);
|
||||
context->pkt_pos = 0;
|
||||
context->pkt = NULL;
|
||||
*len = left + 1;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = left + 1;
|
||||
frame->m = 1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
} else {
|
||||
uint8_t hdr = context->pkt_pos == 0 ? 0x10 : 0;
|
||||
@@ -325,15 +346,13 @@ static switch_status_t consume_partition(vpx_context_t *context, void *data, uin
|
||||
p[0] = hdr;
|
||||
memcpy(p+1, (uint8_t *)context->pkt->data.frame.buf + context->pkt_pos, SLICE_SIZE - 1);
|
||||
context->pkt_pos += (SLICE_SIZE - 1);
|
||||
*len = SLICE_SIZE;
|
||||
frame->datalen = SLICE_SIZE;
|
||||
return SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
vpx_context_t *context = (vpx_context_t *)codec->private_info;
|
||||
uint32_t duration = 90000 / FPS;
|
||||
@@ -341,20 +360,21 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *
|
||||
int height = 0;
|
||||
vpx_enc_frame_flags_t vpx_flags = 0;
|
||||
|
||||
if (*flag & SFF_WAIT_KEY_FRAME) {
|
||||
context->need_key_frame = 1;
|
||||
}
|
||||
|
||||
if (img == NULL) {
|
||||
return consume_partition(context, encoded_data, encoded_data_len, flag);
|
||||
if (frame->flags & SFF_SAME_IMAGE) {
|
||||
return consume_partition(context, frame);
|
||||
}
|
||||
|
||||
//d_w and d_h are messed up
|
||||
//printf("WTF %d %d\n", frame->img->d_w, frame->img->d_h);
|
||||
|
||||
//printf("WTF %d %d\n", img->d_w, img->d_h);
|
||||
|
||||
width = img->w;
|
||||
height = img->h;
|
||||
if (frame->img->d_h > 1) {
|
||||
width = frame->img->d_w;
|
||||
height = frame->img->d_h;
|
||||
} else {
|
||||
width = frame->img->w;
|
||||
height = frame->img->h;
|
||||
}
|
||||
|
||||
//switch_assert(width > 0 && (width % 4 == 0));
|
||||
//switch_assert(height > 0 && (height % 4 == 0));
|
||||
@@ -362,45 +382,43 @@ static switch_status_t switch_vpx_encode(switch_codec_t *codec, switch_image_t *
|
||||
if (context->config.g_w != width || context->config.g_h != height) {
|
||||
context->codec_settings.video.width = width;
|
||||
context->codec_settings.video.height = height;
|
||||
if (context->codec_settings.video.bandwidth) {
|
||||
context->bandwidth = context->codec_settings.video.bandwidth;
|
||||
} else {
|
||||
context->bandwidth = width * height * 8;
|
||||
}
|
||||
|
||||
if (context->bandwidth > 1250000) {
|
||||
context->bandwidth = 1250000;
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(codec->session), SWITCH_LOG_NOTICE,
|
||||
"VPX reset encoder picture from %dx%d to %dx%d %u BW\n",
|
||||
context->config.g_w, context->config.g_h, width, height, context->bandwidth);
|
||||
|
||||
init_codec(codec);
|
||||
*flag |= SFF_PICTURE_RESET;
|
||||
frame->flags |= SFF_PICTURE_RESET;
|
||||
context->need_key_frame = 1;
|
||||
}
|
||||
|
||||
if (context->need_key_frame > 0) {
|
||||
// force generate a key frame
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VPX KEYFRAME REQ\n");
|
||||
vpx_flags |= VPX_EFLAG_FORCE_KF;
|
||||
context->need_key_frame--;
|
||||
|
||||
if (!context->encoder_init) {
|
||||
init_codec(codec);
|
||||
}
|
||||
|
||||
if (vpx_codec_encode(&context->encoder, (vpx_image_t *)img, context->pts, duration, vpx_flags, VPX_DL_REALTIME) != VPX_CODEC_OK) {
|
||||
if (context->need_key_frame != 0) {
|
||||
// force generate a key frame
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "VPX KEYFRAME GENERATED\n");
|
||||
vpx_flags |= VPX_EFLAG_FORCE_KF;
|
||||
context->need_key_frame = 0;
|
||||
}
|
||||
|
||||
if (vpx_codec_encode(&context->encoder, (vpx_image_t *) frame->img, context->pts, duration, vpx_flags, VPX_DL_REALTIME) != VPX_CODEC_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "VP8 encode error %d:%s\n",
|
||||
context->encoder.err, context->encoder.err_detail);
|
||||
|
||||
frame->datalen = 0;
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
context->pts += duration;
|
||||
context->iter = NULL;
|
||||
|
||||
return consume_partition(context, encoded_data, encoded_data_len, flag);
|
||||
return consume_partition(context, frame);
|
||||
}
|
||||
|
||||
static void buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
||||
static switch_status_t buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
||||
{
|
||||
uint8_t *data = frame->data;
|
||||
uint8_t S;
|
||||
@@ -410,7 +428,7 @@ static void buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
||||
|
||||
if (!frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no frame in codec!!\n");
|
||||
return;
|
||||
return SWITCH_STATUS_RESTART;
|
||||
}
|
||||
|
||||
DES = *data;
|
||||
@@ -431,106 +449,119 @@ static void buffer_vpx_packets(vpx_context_t *context, switch_frame_t *frame)
|
||||
}
|
||||
|
||||
len = frame->datalen - (data - (uint8_t *)frame->data);
|
||||
|
||||
if (len <= 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid packet %d\n", len);
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
return;
|
||||
return SWITCH_STATUS_RESTART;
|
||||
}
|
||||
|
||||
|
||||
if (S && (PID == 0)) {
|
||||
uint8_t keyframe;
|
||||
int is_keyframe = ((*data) & 0x01) ? 0 : 1;
|
||||
|
||||
keyframe = ((*data) & 0x01) ? 0 : 1;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "[%d] PID: %d K:%d P:%d Inv:%d len: %d size:%d\n", frame->datalen, PID, keyframe, profile, invisible, len, size);
|
||||
|
||||
if (keyframe) {
|
||||
if (!context->got_key_frame) context->got_key_frame = 1;
|
||||
if (is_keyframe && !context->got_key_frame) {
|
||||
context->got_key_frame = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context->got_key_frame) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Waiting for key frame\n");
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
return;
|
||||
return SWITCH_STATUS_RESTART;
|
||||
}
|
||||
|
||||
switch_buffer_write(context->vpx_packet_buffer, data, len);
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame, switch_image_t **img, unsigned int *flag)
|
||||
static switch_status_t switch_vpx_decode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
vpx_context_t *context = (vpx_context_t *)codec->private_info;
|
||||
vpx_codec_ctx_t *decoder = &context->decoder;
|
||||
switch_size_t len;
|
||||
vpx_codec_ctx_t *decoder = NULL;
|
||||
switch_status_t status = SWITCH_STATUS_SUCCESS;
|
||||
|
||||
if (!decoder) {
|
||||
if (!context->decoder_init) {
|
||||
init_codec(codec);
|
||||
}
|
||||
|
||||
if (!context->decoder_init) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX decoder is not initialized!\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
decoder = &context->decoder;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "len: %d ts: %" SWITCH_SIZE_T_FMT " mark:%d\n", frame->datalen, frame->timestamp, frame->m);
|
||||
|
||||
if (context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
if (context->last_received_timestamp && context->last_received_timestamp != frame->timestamp &&
|
||||
(!frame->m) && (!context->last_received_complete_picture)) {
|
||||
// possible packet loss
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Packet Loss, skip previouse received frame (to avoid crash?)\n");
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Packet Loss, skip previous received frame (to avoid crash?)\n");
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
context->last_received_timestamp = frame->timestamp;
|
||||
context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;
|
||||
|
||||
buffer_vpx_packets(context, frame);
|
||||
status = buffer_vpx_packets(context, frame);
|
||||
|
||||
len = switch_buffer_inuse(context->vpx_packet_buffer);
|
||||
printf("READ buf:%ld got_key:%d st:%d m:%d\n", switch_buffer_inuse(context->vpx_packet_buffer), context->got_key_frame, status, frame->m);
|
||||
|
||||
if (frame->m && len) {
|
||||
if (status == SWITCH_STATUS_SUCCESS && frame->m && (len = switch_buffer_inuse(context->vpx_packet_buffer))) {
|
||||
uint8_t *data;
|
||||
vpx_codec_iter_t iter = NULL;
|
||||
int corrupted = 0;
|
||||
int err;
|
||||
// int keyframe = 0;
|
||||
//int keyframe = 0;
|
||||
|
||||
printf("WTF %d %ld\n", frame->m, len);
|
||||
|
||||
switch_buffer_peek_zerocopy(context->vpx_packet_buffer, (void *)&data);
|
||||
// keyframe = (*data & 0x01) ? 0 : 1;
|
||||
//keyframe = (*data & 0x01) ? 0 : 1;
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffered: %" SWITCH_SIZE_T_FMT ", key: %d\n", len, keyframe);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffered: %" SWITCH_SIZE_T_FMT ", key: %d\n", len, keyframe);
|
||||
|
||||
err = vpx_codec_decode(decoder, data, (unsigned int)len, NULL, 0);
|
||||
|
||||
if (err != VPX_CODEC_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error decoding %" SWITCH_SIZE_T_FMT " bytes, [%d:%d:%s]\n", len, err, decoder->err, decoder->err_detail);
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
context->got_key_frame = 0;
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "require key frame %d\n", context->got_key_frame);
|
||||
goto error;
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
if (vpx_codec_control(decoder, VP8D_GET_FRAME_CORRUPTED, &corrupted) != VPX_CODEC_OK) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "VPX control error!\n");
|
||||
goto error;
|
||||
switch_goto_status(SWITCH_STATUS_RESTART, end);
|
||||
}
|
||||
|
||||
*img = (switch_image_t *)vpx_codec_get_frame(decoder, &iter);
|
||||
frame->img = (switch_image_t *) vpx_codec_get_frame(decoder, &iter);
|
||||
|
||||
if (!(*img) || corrupted) {
|
||||
if (!(frame->img) || corrupted) {
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
goto ok;
|
||||
switch_goto_status(SWITCH_STATUS_SUCCESS, end);
|
||||
}
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%dx%d %dx%d\n", (*img)->w,(*img)->h, (*img)->d_w, (*img)->d_h);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "%dx%d %dx%d\n", frame->img->w,frame->img->h, frame->img->d_w, frame->img->d_h);
|
||||
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
}
|
||||
|
||||
ok:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
end:
|
||||
|
||||
error:
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
if (status == SWITCH_STATUS_RESTART) {
|
||||
context->got_key_frame = 0;
|
||||
switch_buffer_zero(context->vpx_packet_buffer);
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_FALSE;
|
||||
if (!frame->img) {
|
||||
status = SWITCH_STATUS_MORE_DATA;
|
||||
}
|
||||
|
||||
if (!context->got_key_frame) {
|
||||
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -50,25 +50,19 @@ static switch_status_t switch_yuv_init(switch_codec_t *codec, switch_codec_flag_
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t switch_yuv_encode(switch_codec_t *codec,
|
||||
switch_image_t *img,
|
||||
void *encoded_data, uint32_t *encoded_data_len,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_yuv_encode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
/* yuv encode is unclear, so return 0 for now */
|
||||
*encoded_data_len = 0;
|
||||
*flag |= SFF_MARKER;
|
||||
frame->datalen = 0;
|
||||
frame->m = 1;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t switch_yuv_decode(switch_codec_t *codec,
|
||||
switch_frame_t *frame,
|
||||
switch_image_t **img,
|
||||
unsigned int *flag)
|
||||
static switch_status_t switch_yuv_decode(switch_codec_t *codec, switch_frame_t *frame)
|
||||
{
|
||||
switch_assert(frame);
|
||||
|
||||
*img = (switch_image_t *)frame->user_data;
|
||||
frame->img = (switch_image_t *)frame->user_data;
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user