FS-7519: add abndwidth params and fix issue on reset of mov_avcodec

This commit is contained in:
Anthony Minessale 2015-05-12 19:53:26 -05:00 committed by Michael Jerris
parent e050d63e58
commit 22ade18600
1 changed files with 99 additions and 24 deletions

View File

@ -43,7 +43,7 @@
#include <x264.h>
#endif
#define FPS 15 // frame rate
#define FPS 30 // frame rate
SWITCH_MODULE_LOAD_FUNCTION(mod_avcodec_load);
SWITCH_MODULE_DEFINITION(mod_avcodec, mod_avcodec_load, NULL, NULL);
@ -99,6 +99,11 @@ typedef struct h264_codec_context_s {
x264_nal_t *x264_nals;
int x264_nal_count;
int cur_nalu_index;
int change_bandwidth;
unsigned int bandwidth;
switch_codec_settings_t codec_settings;
#endif
} h264_codec_context_t;
@ -109,17 +114,47 @@ static switch_status_t init_x264(h264_codec_context_t *context, uint32_t width,
{
x264_t *xh = context->x264_handle;
x264_param_t *xp = &context->x264_params;
int ret = 0;
//int ret = 0;
if (width && height) {
context->codec_settings.video.width = width;
context->codec_settings.video.height = height;
}
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 / 1024;
}
if (context->bandwidth > 5120) {
context->bandwidth = 5120;
}
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "initializing x264 handle %dx%d bw:%d\n", width, height, context->bandwidth);
if (xh) {
xp->i_width = width;
xp->i_height = height;
ret = x264_encoder_reconfig(xh, xp);
x264_encoder_close(context->x264_handle);
context->x264_handle = xh = NULL;
switch_buffer_zero(context->nalu_buffer);
//xp->i_width = width;
//xp->i_height = height;
//ret = x264_encoder_reconfig(xh, xp);
if (ret == 0) return SWITCH_STATUS_SUCCESS;
//if (ret == 0) return SWITCH_STATUS_SUCCESS;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot Reset error:%d\n", ret);
return SWITCH_STATUS_FALSE;
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Cannot Reset error:%d\n", ret);
//return SWITCH_STATUS_FALSE;
}
// x264_param_default(xp);
@ -129,8 +164,8 @@ static switch_status_t init_x264(h264_codec_context_t *context, uint32_t width,
// xp->i_threads = 1;//X264_SYNC_LOOKAHEAD_AUTO;
// xp->i_lookahead_threads = X264_SYNC_LOOKAHEAD_AUTO;
// Video Properties
xp->i_width = width;
xp->i_height = height;
xp->i_width = context->codec_settings.video.width;
xp->i_height = context->codec_settings.video.height;
xp->i_frame_total = 0;
xp->i_keyint_max = FPS * 10;
// Bitstream parameters
@ -145,10 +180,10 @@ static switch_status_t init_x264(h264_codec_context_t *context, uint32_t width,
// xp->i_log_level = X264_LOG_DEBUG;
xp->i_log_level = X264_LOG_NONE;
// Rate control Parameters
xp->rc.i_bitrate = 378;//kbps
xp->rc.i_bitrate = context->bandwidth;
// Muxing parameters
xp->i_fps_den = 1;
xp->i_fps_num = FPS;
//xp->i_fps_den = 1;
//xp->i_fps_num = FPS;
xp->i_timebase_den = xp->i_fps_num;
xp->i_timebase_num = xp->i_fps_den;
xp->i_slice_max_size = SLICE_SIZE;
@ -210,7 +245,7 @@ static switch_status_t nalu_slice(h264_codec_context_t *context, switch_frame_t
static uint8_t ff_input_buffer_padding[FF_INPUT_BUFFER_PADDING_SIZE] = { 0 };
static void buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *frame)
static switch_status_t buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *frame)
{
uint8_t nalu_type = 0;
uint8_t *data = frame->data;
@ -224,8 +259,7 @@ static void buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *fram
if (!context->got_pps && nalu_type != 7) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "waiting pps\n");
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
return;
return SWITCH_STATUS_RESTART;
}
if (!context->got_pps) context->got_pps = 1;
@ -239,7 +273,7 @@ static void buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *fram
nalu_type = *(data + 1) & 0x1f;
if (start && end) return;
if (start && end) return SWITCH_STATUS_RESTART;
if (start) {
if (context->nalu_28_start) {
@ -249,7 +283,7 @@ static void buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *fram
} else if (end) {
context->nalu_28_start = 0;
} else if (!context->nalu_28_start) {
return;
return SWITCH_STATUS_RESTART;
}
if (start) {
@ -272,6 +306,8 @@ static void buffer_h264_nalu(h264_codec_context_t *context, switch_frame_t *fram
switch_buffer_write(buffer, ff_input_buffer_padding, sizeof(ff_input_buffer_padding));
context->nalu_28_start = 0;
}
return SWITCH_STATUS_SUCCESS;
}
#ifndef H264_CODEC_USE_LIBX264
@ -356,7 +392,7 @@ static switch_status_t open_encoder(h264_codec_context_t *context, uint32_t widt
context->encoder_ctx->width = width;
context->encoder_ctx->height = height;
/* frames per second */
context->encoder_ctx->time_base= (AVRational){1, FPS};
context->encoder_ctx->time_base = (AVRational){1, 90000};
context->encoder_ctx->gop_size = FPS * 3; /* emit one intra frame every 3 seconds */
context->encoder_ctx->max_b_frames = 0;
context->encoder_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
@ -394,6 +430,11 @@ static switch_status_t switch_h264_init(switch_codec_t *codec, switch_codec_flag
switch_assert(context);
memset(context, 0, sizeof(*context));
if (codec_settings) {
context->codec_settings = *codec_settings;
}
if (decoding) {
context->decoder = avcodec_find_decoder(AV_CODEC_ID_H264);
@ -589,17 +630,25 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
switch_image_t *img = frame->img;
void *encoded_data = frame->data;
uint32_t *encoded_data_len = &frame->datalen;
unsigned int *flag = &frame->flags;
//unsigned int *flag = &frame->flags;
if (*flag & SFF_WAIT_KEY_FRAME) context->need_key_frame = 1;
//if (*flag & SFF_WAIT_KEY_FRAME) context->need_key_frame = 1;
//if (*encoded_data_len < SWITCH_DEFAULT_VIDEO_SIZE) return SWITCH_STATUS_FALSE;
if (!context) return SWITCH_STATUS_FALSE;
if (context->change_bandwidth) {
context->codec_settings.video.bandwidth = context->change_bandwidth;
context->change_bandwidth = 0;
init_x264(context, 0, 0);
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
}
if (!context->x264_handle) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "initializing x264 handle %dx%d\n", width, height);
init_x264(context, width, height);
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
}
if (frame->flags & SFF_SAME_IMAGE) {
@ -611,8 +660,9 @@ static switch_status_t switch_h264_encode(switch_codec_t *codec,
if (context->x264_params.i_width != width || context->x264_params.i_height != height) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "picture size changed from %dx%d to %dx%d, reinitializing encoder\n",
context->x264_params.i_width, context->x264_params.i_width, width, height);
context->x264_params.i_width, context->x264_params.i_width, width, height);
init_x264(context, width, height);
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
}
switch_assert(encoded_data);
@ -673,6 +723,7 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec, switch_frame_t
{
h264_codec_context_t *context = (h264_codec_context_t *)codec->private_info;
AVCodecContext *avctx= context->decoder_ctx;
switch_status_t status;
switch_assert(frame);
@ -688,7 +739,14 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec, switch_frame_t
context->last_received_timestamp = frame->timestamp;
context->last_received_complete_picture = frame->m ? SWITCH_TRUE : SWITCH_FALSE;
buffer_h264_nalu(context, frame);
status = buffer_h264_nalu(context, frame);
if (status == SWITCH_STATUS_RESTART) {
switch_set_flag(frame, SFF_WAIT_KEY_FRAME);
switch_buffer_zero(context->nalu_buffer);
context->nalu_28_start = 0;
return SWITCH_STATUS_MORE_DATA;
}
if (frame->m) {
uint32_t size = switch_buffer_inuse(context->nalu_buffer);
@ -760,6 +818,23 @@ static switch_status_t switch_h264_control(switch_codec_t *codec,
case SCC_VIDEO_REFRESH:
context->need_key_frame = 1;
break;
case SCC_VIDEO_BANDWIDTH:
{
switch(ctype) {
case SCCT_INT:
context->change_bandwidth = *((int *) cmd_data);
break;
case SCCT_STRING:
{
char *bwv = (char *) cmd_data;
context->change_bandwidth = switch_parse_bandwidth_string(bwv);
}
break;
default:
break;
}
}
break;
default:
break;
}