diff --git a/src/include/switch_core_video.h b/src/include/switch_core_video.h index 00b9de4175..c836c05a22 100644 --- a/src/include/switch_core_video.h +++ b/src/include/switch_core_video.h @@ -368,6 +368,19 @@ SWITCH_DECLARE(switch_image_t *) switch_img_write_text_img(int w, int h, switch_ SWITCH_DECLARE(switch_image_t *) switch_img_read_file(const char* file_name); SWITCH_DECLARE(switch_status_t) switch_img_letterbox(switch_image_t *img, switch_image_t **imgP, int width, int height, const char *color); SWITCH_DECLARE(switch_bool_t) switch_core_has_video(void); + +/*!\brief I420 to I420 Copy*/ + +SWITCH_DECLARE(switch_status_t) switch_I420_copy(const uint8_t* src_y, int src_stride_y, + const uint8_t* src_u, int src_stride_u, + const uint8_t* src_v, int src_stride_v, + uint8_t* dst_y, int dst_stride_y, + uint8_t* dst_u, int dst_stride_u, + uint8_t* dst_v, int dst_stride_v, + int width, int height); +SWITCH_DECLARE(switch_status_t) switch_I420_copy2(uint8_t *src_planes[], int src_stride[], + uint8_t *dst_planes[], int dst_stride[], + int width, int height); /** @} */ SWITCH_END_EXTERN_C diff --git a/src/mod/applications/mod_av/avcodec.c b/src/mod/applications/mod_av/avcodec.c index ac9634fdcf..f8b283c3a8 100644 --- a/src/mod/applications/mod_av/avcodec.c +++ b/src/mod/applications/mod_av/avcodec.c @@ -181,6 +181,7 @@ typedef struct h264_codec_context_s { AVCodecContext *encoder_ctx; AVFrame *encoder_avframe; AVPacket encoder_avpacket; + AVFrame *decoder_avframe; our_h264_nalu_t nalus[MAX_NALUS]; enum AVCodecID av_codec_id; uint16_t last_seq; // last received frame->seq @@ -990,22 +991,9 @@ error: static void __attribute__((unused)) fill_avframe(AVFrame *pict, switch_image_t *img) { - int i; - uint8_t *y = img->planes[0]; - uint8_t *u = img->planes[1]; - uint8_t *v = img->planes[2]; - - /* Y */ - for (i = 0; i < pict->height; i++) { - memcpy(&pict->data[0][i * pict->linesize[0]], y + i * img->stride[0], pict->width); - } - - /* U/V */ - for(i = 0; i < pict->height / 2; i++) { - memcpy(&pict->data[1][i * pict->linesize[1]], u + i * img->stride[1], pict->width / 2); - memcpy(&pict->data[2][i * pict->linesize[2]], v + i * img->stride[2], pict->width / 2); - } - + switch_I420_copy2(img->planes, img->stride, + pict->data, pict->linesize, + img->d_w, img->d_h); } static switch_status_t switch_h264_encode(switch_codec_t *codec, switch_frame_t *frame) @@ -1237,57 +1225,40 @@ static switch_status_t switch_h264_decode(switch_codec_t *codec, switch_frame_t if (size > 0) { av_init_packet(&pkt); - pkt.data = NULL; - pkt.size = 0; switch_buffer_write(context->nalu_buffer, ff_input_buffer_padding, sizeof(ff_input_buffer_padding)); switch_buffer_peek_zerocopy(context->nalu_buffer, (const void **)&pkt.data); pkt.size = size; - picture = av_frame_alloc(); - assert(picture); + + if (!context->decoder_avframe) context->decoder_avframe = av_frame_alloc(); + picture = context->decoder_avframe; + switch_assert(picture); decoded_len = avcodec_decode_video2(avctx, picture, &got_picture, &pkt); - // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer: %d got pic: %d len: %d [%dx%d]\n", size, got_picture, decoded_len, avctx->width, avctx->height); + // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "buffer: %d got pic: %d len: %d [%dx%d]\n", size, got_picture, decoded_len, picture->width, picture->height); if (got_picture && decoded_len > 0) { - int width = avctx->width; - int height = avctx->height; - int i; + int width = picture->width; + int height = picture->height; if (!context->img || (context->img->d_w != width || context->img->d_h != height)) { - //context->img = switch_img_wrap(NULL, SWITCH_IMG_FMT_I420, width, height, 0, picture->data[0]); + switch_img_free(&context->img); context->img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, width, height, 1); - assert(context->img); + switch_assert(context->img); } - +#if 0 context->img->w = picture->linesize[0]; context->img->h = picture->linesize[1]; context->img->d_w = width; context->img->d_h = height; - - //context->img->planes[0] = picture->data[0]; - //context->img->planes[1] = picture->data[1]; - //context->img->planes[2] = picture->data[2]; - //context->img->stride[0] = picture->linesize[0]; - //context->img->stride[1] = picture->linesize[1]; - //context->img->stride[2] = picture->linesize[2]; - - for (i = 0; i < height; i++) { - memcpy(context->img->planes[SWITCH_PLANE_Y] + context->img->stride[SWITCH_PLANE_Y] * i, - picture->data[SWITCH_PLANE_Y] + picture->linesize[SWITCH_PLANE_Y] * i, width); - } - - for (i = 0; i < height / 2; i++) { - memcpy(context->img->planes[SWITCH_PLANE_U] + context->img->stride[SWITCH_PLANE_U] * i, - picture->data[SWITCH_PLANE_U] + picture->linesize[SWITCH_PLANE_U] * i, width / 2); - memcpy(context->img->planes[SWITCH_PLANE_V] + context->img->stride[SWITCH_PLANE_V] * i, - picture->data[SWITCH_PLANE_V] + picture->linesize[SWITCH_PLANE_V] * i, width / 2); - } +#endif + switch_I420_copy2(picture->data, picture->linesize, + context->img->planes, context->img->stride, + width, height); frame->img = context->img; } - av_frame_free(&picture); - av_free_packet(&pkt); + av_frame_unref(picture); } switch_buffer_zero(context->nalu_buffer); @@ -1366,6 +1337,10 @@ static switch_status_t switch_h264_destroy(switch_codec_t *codec) av_frame_free(&context->encoder_avframe); } + if (context->decoder_avframe) { + av_frame_free(&context->decoder_avframe); + } + return SWITCH_STATUS_SUCCESS; } diff --git a/src/switch_core_video.c b/src/switch_core_video.c index 6e65394b9f..3cef5b2919 100644 --- a/src/switch_core_video.c +++ b/src/switch_core_video.c @@ -2182,6 +2182,33 @@ SWITCH_DECLARE(switch_image_t *) switch_img_read_file(const char* file_name) } #endif +SWITCH_DECLARE(switch_status_t) switch_I420_copy(const uint8* src_y, int src_stride_y, + const uint8* src_u, int src_stride_u, + const uint8* src_v, int src_stride_v, + uint8* dst_y, int dst_stride_y, + uint8* dst_u, int dst_stride_u, + uint8* dst_v, int dst_stride_v, + int width, int height) +{ + int ret = I420Copy(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, + dst_y, dst_stride_y, dst_u, dst_stride_u, dst_v, dst_stride_v, + width, height); + return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; +} + +SWITCH_DECLARE(switch_status_t) switch_I420_copy2(uint8_t *src_planes[], int src_stride[], + uint8_t *dst_planes[], int dst_stride[], + int width, int height) +{ + int ret = I420Copy(src_planes[SWITCH_PLANE_Y], src_stride[SWITCH_PLANE_Y], + src_planes[SWITCH_PLANE_U], src_stride[SWITCH_PLANE_U], + src_planes[SWITCH_PLANE_V], src_stride[SWITCH_PLANE_V], + dst_planes[SWITCH_PLANE_Y], dst_stride[SWITCH_PLANE_Y], + dst_planes[SWITCH_PLANE_U], dst_stride[SWITCH_PLANE_U], + dst_planes[SWITCH_PLANE_V], dst_stride[SWITCH_PLANE_V], + width, height); + return ret == 0 ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE; +} /* For Emacs: * Local Variables: * mode:c