Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn native

2019-05-15 Thread Pedro Arthur
Em qua, 15 de mai de 2019 às 04:44, Steven Liu
 escreveu:
>
> Xuewei Meng  于2019年5月11日周六 上午11:11写道:
> >
> > ---
> >  libavfilter/dnn_backend_native.c | 52 
> >  libavfilter/dnn_backend_native.h |  3 ++
> >  2 files changed, 43 insertions(+), 12 deletions(-)
> >
> > diff --git a/libavfilter/dnn_backend_native.c 
> > b/libavfilter/dnn_backend_native.c
> > index 06fbdf368b..171a756385 100644
> > --- a/libavfilter/dnn_backend_native.c
> > +++ b/libavfilter/dnn_backend_native.c
> > @@ -61,6 +61,12 @@ static DNNReturnType set_input_output_native(void 
> > *model, DNNInputData *input, c
> >  return DNN_ERROR;
> >  }
> >  cur_channels = conv_params->output_num;
> > +
> > +if(conv_params->padding_method == VALID){
> > +int pad_size = conv_params->kernel_size - 1;
> > +cur_height -= pad_size;
> > +cur_width -= pad_size;
> > +}
> >  break;
> >  case DEPTH_TO_SPACE:
> >  depth_to_space_params = (DepthToSpaceParams 
> > *)network->layers[layer].params;
> > @@ -77,6 +83,10 @@ static DNNReturnType set_input_output_native(void 
> > *model, DNNInputData *input, c
> >  if (network->layers[layer].output){
> >  av_freep(>layers[layer].output);
> >  }
> > +
> > +if(cur_height <= 0 || cur_width <= 0)
> > +return DNN_ERROR;
> > +
> >  network->layers[layer].output = av_malloc(cur_height * cur_width * 
> > cur_channels * sizeof(float));
> >  if (!network->layers[layer].output){
> >  return DNN_ERROR;
> > @@ -154,13 +164,14 @@ DNNModel *ff_dnn_load_model_native(const char 
> > *model_filename)
> >  ff_dnn_free_model_native();
> >  return NULL;
> >  }
> > +conv_params->padding_method = 
> > (int32_t)avio_rl32(model_file_context);
> >  conv_params->activation = 
> > (int32_t)avio_rl32(model_file_context);
> >  conv_params->input_num = 
> > (int32_t)avio_rl32(model_file_context);
> >  conv_params->output_num = 
> > (int32_t)avio_rl32(model_file_context);
> >  conv_params->kernel_size = 
> > (int32_t)avio_rl32(model_file_context);
> >  kernel_size = conv_params->input_num * conv_params->output_num 
> > *
> >conv_params->kernel_size * 
> > conv_params->kernel_size;
> > -dnn_size += 16 + (kernel_size + conv_params->output_num << 2);
> > +dnn_size += 20 + (kernel_size + conv_params->output_num << 2);
> >  if (dnn_size > file_size || conv_params->input_num <= 0 ||
> >  conv_params->output_num <= 0 || conv_params->kernel_size 
> > <= 0){
> >  avio_closep(_file_context);
> > @@ -218,23 +229,35 @@ DNNModel *ff_dnn_load_model_native(const char 
> > *model_filename)
> >
> >  static void convolve(const float *input, float *output, const 
> > ConvolutionalParams *conv_params, int width, int height)
> >  {
> > -int y, x, n_filter, ch, kernel_y, kernel_x;
> >  int radius = conv_params->kernel_size >> 1;
> >  int src_linesize = width * conv_params->input_num;
> >  int filter_linesize = conv_params->kernel_size * 
> > conv_params->input_num;
> >  int filter_size = conv_params->kernel_size * filter_linesize;
> > +int pad_size = (conv_params->padding_method == VALID) ? 
> > (conv_params->kernel_size - 1) / 2 : 0;
> >
> > -for (y = 0; y < height; ++y){
> > -for (x = 0; x < width; ++x){
> > -for (n_filter = 0; n_filter < conv_params->output_num; 
> > ++n_filter){
> > +for (int y = pad_size; y < height - pad_size; ++y){
> > +for (int x = pad_size; x < width - pad_size; ++x){
> > +for (int n_filter = 0; n_filter < conv_params->output_num; 
> > ++n_filter){
> >  output[n_filter] = conv_params->biases[n_filter];
> > -for (ch = 0; ch < conv_params->input_num; ++ch){
> > -for (kernel_y = 0; kernel_y < 
> > conv_params->kernel_size; ++kernel_y){
> > -for (kernel_x = 0; kernel_x < 
> > conv_params->kernel_size; ++kernel_x){
> > -output[n_filter] += input[CLAMP_TO_EDGE(y + 
> > kernel_y - radius, height) * src_linesize +
> > -  CLAMP_TO_EDGE(x + 
> > kernel_x - radius, width) * conv_params->input_num + ch] *
> > -
> > conv_params->kernel[n_filter * filter_size + kernel_y * filter_linesize +
> > -
> > kernel_x * conv_params->input_num + ch];
> > +
> > +for (int ch = 0; ch < conv_params->input_num; ++ch){
> > +for (int kernel_y = 0; kernel_y < 
> > conv_params->kernel_size; ++kernel_y){
> > +for (int kernel_x = 

Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn native

2019-05-15 Thread Guo, Yejun

> 
> 
> From: Xuewei Meng [mailto:xwmen...@gmail.com]
> Sent: Wednesday, May 15, 2019 4:41 PM
> To: Guo, Yejun 
> Cc: FFmpeg development discussions and patches 
> Subject: Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn
> native
> 
> 
> 
> Guo, Yejun  于2019年5月15日周三 下午2:21写道:
> 
> 
> > -Original Message-
> > From: ffmpeg-devel [mailto:ffmpeg-devel-boun...@ffmpeg.org] On Behalf Of
> > Steven Liu
> > Sent: Wednesday, May 15, 2019 10:38 AM
> > To: FFmpeg development discussions and patches
> 
> > Cc: Xuewei Meng 
> > Subject: Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn
> > native
> >
> > Xuewei Meng  于2019年5月11日周六 上午
> 11:11
> > 写道:
> > >
> > > ---
> > >  libavfilter/dnn_backend_native.c | 52 
> > >  libavfilter/dnn_backend_native.h |  3 ++
> > >  2 files changed, 43 insertions(+), 12 deletions(-)
> 
> @xuewei, we still need to mention the impact of sr filter, and explain why
> same_clamp_to_edge is needed.
> There are three padding methods in this patch, VALID, SAME and
> SAME_CLAMP_TO_EDGE. The 'VALID' and 'SAME' options are tensorflow
> supported padding methods. And the third one, 'SAME_CLAMP_TO_EDGE', is
> suggested by sr filter. As this method can keep the output with the same size
> as original input, and gives a slight better result as mentioned by Pedro 
> Arthur.
> So we keep this option in dnn native mode.

nice, please add them into commit log. And also the impact to sr filter.

> 
> > >
> > > diff --git a/libavfilter/dnn_backend_native.c
> > b/libavfilter/dnn_backend_native.c
> > > index 06fbdf368b..171a756385 100644
> > > --- a/libavfilter/dnn_backend_native.c
> > > +++ b/libavfilter/dnn_backend_native.c
> > > @@ -61,6 +61,12 @@ static DNNReturnType
> set_input_output_native(void
> > *model, DNNInputData *input, c
> > >                  return DNN_ERROR;
> > >              }
> > >              cur_channels = conv_params->output_num;
> > > +
> > > +            if(conv_params->padding_method == VALID){
> > > +                int pad_size = conv_params->kernel_size - 1;
> > > +                cur_height -= pad_size;
> > > +                cur_width -= pad_size;
> > > +            }
> > >              break;
> > >          case DEPTH_TO_SPACE:
> > >              depth_to_space_params = (DepthToSpaceParams
> > *)network->layers[layer].params;
> > > @@ -77,6 +83,10 @@ static DNNReturnType
> set_input_output_native(void
> > *model, DNNInputData *input, c
> > >          if (network->layers[layer].output){
> > >              av_freep(>layers[layer].output);
> > >          }
> > > +
> > > +        if(cur_height <= 0 || cur_width <= 0)
> > > +            return DNN_ERROR;
> > > +
> > >          network->layers[layer].output = av_malloc(cur_height *
> > cur_width * cur_channels * sizeof(float));
> > >          if (!network->layers[layer].output){
> > >              return DNN_ERROR;
> > > @@ -154,13 +164,14 @@ DNNModel *ff_dnn_load_model_native(const
> > char *model_filename)
> > >                  ff_dnn_free_model_native();
> > >                  return NULL;
> > >              }
> > > +            conv_params->padding_method =
> > (int32_t)avio_rl32(model_file_context);
> > >              conv_params->activation =
> > (int32_t)avio_rl32(model_file_context);
> > >              conv_params->input_num =
> > (int32_t)avio_rl32(model_file_context);
> > >              conv_params->output_num =
> > (int32_t)avio_rl32(model_file_context);
> > >              conv_params->kernel_size =
> > (int32_t)avio_rl32(model_file_context);
> > >              kernel_size = conv_params->input_num *
> > conv_params->output_num *
> > >                            conv_params->kernel_size *
> > conv_params->kernel_size;
> > > -            dnn_size += 16 + (kernel_size + conv_params->output_num
> > << 2);
> > > +            dnn_size += 20 + (kernel_size +
> conv_params->output_num
> > << 2);
> > >              if (dnn_size > file_size || conv_params->input_num <= 0
> ||
> > >                  conv_params->output_num <= 0 ||
> > conv_params->kernel_size <= 0){
> > >                  avio_closep(_file_context);
> > > @@ -218,23 +229,35 @@ DNNModel 

Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn native

2019-05-15 Thread Xuewei Meng
Guo, Yejun  于2019年5月15日周三 下午2:21写道:

>
>
> > -Original Message-
> > From: ffmpeg-devel [mailto:ffmpeg-devel-boun...@ffmpeg.org] On Behalf Of
> > Steven Liu
> > Sent: Wednesday, May 15, 2019 10:38 AM
> > To: FFmpeg development discussions and patches 
> > Cc: Xuewei Meng 
> > Subject: Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn
> > native
> >
> > Xuewei Meng  于2019年5月11日周六 上午11:11
> > 写道:
> > >
> > > ---
> > >  libavfilter/dnn_backend_native.c | 52 
> > >  libavfilter/dnn_backend_native.h |  3 ++
> > >  2 files changed, 43 insertions(+), 12 deletions(-)
>
> @xuewei, we still need to mention the impact of sr filter, and explain why
> same_clamp_to_edge is needed.
>
> There are three padding methods in this patch, VALID, SAME and
SAME_CLAMP_TO_EDGE. The 'VALID' and 'SAME' options are tensorflow supported
padding methods. And the third one, 'SAME_CLAMP_TO_EDGE', is suggested by
sr filter. As this method can keep the output with the same size as
original input, and gives a slight better result as mentioned by Pedro
Arthur. So we keep this option in dnn native mode.


> > >
> > > diff --git a/libavfilter/dnn_backend_native.c
> > b/libavfilter/dnn_backend_native.c
> > > index 06fbdf368b..171a756385 100644
> > > --- a/libavfilter/dnn_backend_native.c
> > > +++ b/libavfilter/dnn_backend_native.c
> > > @@ -61,6 +61,12 @@ static DNNReturnType set_input_output_native(void
> > *model, DNNInputData *input, c
> > >  return DNN_ERROR;
> > >  }
> > >  cur_channels = conv_params->output_num;
> > > +
> > > +if(conv_params->padding_method == VALID){
> > > +int pad_size = conv_params->kernel_size - 1;
> > > +cur_height -= pad_size;
> > > +cur_width -= pad_size;
> > > +}
> > >  break;
> > >  case DEPTH_TO_SPACE:
> > >  depth_to_space_params = (DepthToSpaceParams
> > *)network->layers[layer].params;
> > > @@ -77,6 +83,10 @@ static DNNReturnType set_input_output_native(void
> > *model, DNNInputData *input, c
> > >  if (network->layers[layer].output){
> > >  av_freep(>layers[layer].output);
> > >  }
> > > +
> > > +if(cur_height <= 0 || cur_width <= 0)
> > > +return DNN_ERROR;
> > > +
> > >  network->layers[layer].output = av_malloc(cur_height *
> > cur_width * cur_channels * sizeof(float));
> > >  if (!network->layers[layer].output){
> > >  return DNN_ERROR;
> > > @@ -154,13 +164,14 @@ DNNModel *ff_dnn_load_model_native(const
> > char *model_filename)
> > >  ff_dnn_free_model_native();
> > >  return NULL;
> > >  }
> > > +conv_params->padding_method =
> > (int32_t)avio_rl32(model_file_context);
> > >  conv_params->activation =
> > (int32_t)avio_rl32(model_file_context);
> > >  conv_params->input_num =
> > (int32_t)avio_rl32(model_file_context);
> > >  conv_params->output_num =
> > (int32_t)avio_rl32(model_file_context);
> > >  conv_params->kernel_size =
> > (int32_t)avio_rl32(model_file_context);
> > >  kernel_size = conv_params->input_num *
> > conv_params->output_num *
> > >conv_params->kernel_size *
> > conv_params->kernel_size;
> > > -dnn_size += 16 + (kernel_size + conv_params->output_num
> > << 2);
> > > +dnn_size += 20 + (kernel_size + conv_params->output_num
> > << 2);
> > >  if (dnn_size > file_size || conv_params->input_num <= 0 ||
> > >  conv_params->output_num <= 0 ||
> > conv_params->kernel_size <= 0){
> > >  avio_closep(_file_context);
> > > @@ -218,23 +229,35 @@ DNNModel *ff_dnn_load_model_native(const
> > char *model_filename)
> > >
> > >  static void convolve(const float *input, float *output, const
> > ConvolutionalParams *conv_params, int width, int height)
> > >  {
> > > -int y, x, n_filter, ch, kernel_y, kernel_x;
> > >  int radius = conv_params->kernel_size >> 1;
> > >  int src_linesize = width * conv_params-&g

Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn native

2019-05-15 Thread Guo, Yejun


> -Original Message-
> From: ffmpeg-devel [mailto:ffmpeg-devel-boun...@ffmpeg.org] On Behalf Of
> Steven Liu
> Sent: Wednesday, May 15, 2019 10:38 AM
> To: FFmpeg development discussions and patches 
> Cc: Xuewei Meng 
> Subject: Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn
> native
> 
> Xuewei Meng  于2019年5月11日周六 上午11:11
> 写道:
> >
> > ---
> >  libavfilter/dnn_backend_native.c | 52 
> >  libavfilter/dnn_backend_native.h |  3 ++
> >  2 files changed, 43 insertions(+), 12 deletions(-)

@xuewei, we still need to mention the impact of sr filter, and explain why 
same_clamp_to_edge is needed.

> >
> > diff --git a/libavfilter/dnn_backend_native.c
> b/libavfilter/dnn_backend_native.c
> > index 06fbdf368b..171a756385 100644
> > --- a/libavfilter/dnn_backend_native.c
> > +++ b/libavfilter/dnn_backend_native.c
> > @@ -61,6 +61,12 @@ static DNNReturnType set_input_output_native(void
> *model, DNNInputData *input, c
> >  return DNN_ERROR;
> >  }
> >  cur_channels = conv_params->output_num;
> > +
> > +if(conv_params->padding_method == VALID){
> > +int pad_size = conv_params->kernel_size - 1;
> > +cur_height -= pad_size;
> > +cur_width -= pad_size;
> > +}
> >  break;
> >  case DEPTH_TO_SPACE:
> >  depth_to_space_params = (DepthToSpaceParams
> *)network->layers[layer].params;
> > @@ -77,6 +83,10 @@ static DNNReturnType set_input_output_native(void
> *model, DNNInputData *input, c
> >  if (network->layers[layer].output){
> >  av_freep(>layers[layer].output);
> >  }
> > +
> > +if(cur_height <= 0 || cur_width <= 0)
> > +return DNN_ERROR;
> > +
> >  network->layers[layer].output = av_malloc(cur_height *
> cur_width * cur_channels * sizeof(float));
> >  if (!network->layers[layer].output){
> >  return DNN_ERROR;
> > @@ -154,13 +164,14 @@ DNNModel *ff_dnn_load_model_native(const
> char *model_filename)
> >  ff_dnn_free_model_native();
> >  return NULL;
> >  }
> > +conv_params->padding_method =
> (int32_t)avio_rl32(model_file_context);
> >  conv_params->activation =
> (int32_t)avio_rl32(model_file_context);
> >  conv_params->input_num =
> (int32_t)avio_rl32(model_file_context);
> >  conv_params->output_num =
> (int32_t)avio_rl32(model_file_context);
> >  conv_params->kernel_size =
> (int32_t)avio_rl32(model_file_context);
> >  kernel_size = conv_params->input_num *
> conv_params->output_num *
> >conv_params->kernel_size *
> conv_params->kernel_size;
> > -dnn_size += 16 + (kernel_size + conv_params->output_num
> << 2);
> > +dnn_size += 20 + (kernel_size + conv_params->output_num
> << 2);
> >  if (dnn_size > file_size || conv_params->input_num <= 0 ||
> >  conv_params->output_num <= 0 ||
> conv_params->kernel_size <= 0){
> >  avio_closep(_file_context);
> > @@ -218,23 +229,35 @@ DNNModel *ff_dnn_load_model_native(const
> char *model_filename)
> >
> >  static void convolve(const float *input, float *output, const
> ConvolutionalParams *conv_params, int width, int height)
> >  {
> > -int y, x, n_filter, ch, kernel_y, kernel_x;
> >  int radius = conv_params->kernel_size >> 1;
> >  int src_linesize = width * conv_params->input_num;
> >  int filter_linesize = conv_params->kernel_size *
> conv_params->input_num;
> >  int filter_size = conv_params->kernel_size * filter_linesize;
> > +int pad_size = (conv_params->padding_method == VALID) ?
> (conv_params->kernel_size - 1) / 2 : 0;
> >
> > -for (y = 0; y < height; ++y){
> > -for (x = 0; x < width; ++x){
> > -for (n_filter = 0; n_filter < conv_params->output_num;
> ++n_filter){
> > +for (int y = pad_size; y < height - pad_size; ++y){
> > +for (int x = pad_size; x < width - pad_size; ++x){
> > +for (int n_filter = 0; n_filter < conv_params->output_num;
> ++n_filter){
> >  output[n_filter] = conv_params->biases[n_filter];
> > -

Re: [FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn native

2019-05-14 Thread Steven Liu
Xuewei Meng  于2019年5月11日周六 上午11:11写道:
>
> ---
>  libavfilter/dnn_backend_native.c | 52 
>  libavfilter/dnn_backend_native.h |  3 ++
>  2 files changed, 43 insertions(+), 12 deletions(-)
>
> diff --git a/libavfilter/dnn_backend_native.c 
> b/libavfilter/dnn_backend_native.c
> index 06fbdf368b..171a756385 100644
> --- a/libavfilter/dnn_backend_native.c
> +++ b/libavfilter/dnn_backend_native.c
> @@ -61,6 +61,12 @@ static DNNReturnType set_input_output_native(void *model, 
> DNNInputData *input, c
>  return DNN_ERROR;
>  }
>  cur_channels = conv_params->output_num;
> +
> +if(conv_params->padding_method == VALID){
> +int pad_size = conv_params->kernel_size - 1;
> +cur_height -= pad_size;
> +cur_width -= pad_size;
> +}
>  break;
>  case DEPTH_TO_SPACE:
>  depth_to_space_params = (DepthToSpaceParams 
> *)network->layers[layer].params;
> @@ -77,6 +83,10 @@ static DNNReturnType set_input_output_native(void *model, 
> DNNInputData *input, c
>  if (network->layers[layer].output){
>  av_freep(>layers[layer].output);
>  }
> +
> +if(cur_height <= 0 || cur_width <= 0)
> +return DNN_ERROR;
> +
>  network->layers[layer].output = av_malloc(cur_height * cur_width * 
> cur_channels * sizeof(float));
>  if (!network->layers[layer].output){
>  return DNN_ERROR;
> @@ -154,13 +164,14 @@ DNNModel *ff_dnn_load_model_native(const char 
> *model_filename)
>  ff_dnn_free_model_native();
>  return NULL;
>  }
> +conv_params->padding_method = 
> (int32_t)avio_rl32(model_file_context);
>  conv_params->activation = (int32_t)avio_rl32(model_file_context);
>  conv_params->input_num = (int32_t)avio_rl32(model_file_context);
>  conv_params->output_num = (int32_t)avio_rl32(model_file_context);
>  conv_params->kernel_size = 
> (int32_t)avio_rl32(model_file_context);
>  kernel_size = conv_params->input_num * conv_params->output_num *
>conv_params->kernel_size * 
> conv_params->kernel_size;
> -dnn_size += 16 + (kernel_size + conv_params->output_num << 2);
> +dnn_size += 20 + (kernel_size + conv_params->output_num << 2);
>  if (dnn_size > file_size || conv_params->input_num <= 0 ||
>  conv_params->output_num <= 0 || conv_params->kernel_size <= 
> 0){
>  avio_closep(_file_context);
> @@ -218,23 +229,35 @@ DNNModel *ff_dnn_load_model_native(const char 
> *model_filename)
>
>  static void convolve(const float *input, float *output, const 
> ConvolutionalParams *conv_params, int width, int height)
>  {
> -int y, x, n_filter, ch, kernel_y, kernel_x;
>  int radius = conv_params->kernel_size >> 1;
>  int src_linesize = width * conv_params->input_num;
>  int filter_linesize = conv_params->kernel_size * conv_params->input_num;
>  int filter_size = conv_params->kernel_size * filter_linesize;
> +int pad_size = (conv_params->padding_method == VALID) ? 
> (conv_params->kernel_size - 1) / 2 : 0;
>
> -for (y = 0; y < height; ++y){
> -for (x = 0; x < width; ++x){
> -for (n_filter = 0; n_filter < conv_params->output_num; 
> ++n_filter){
> +for (int y = pad_size; y < height - pad_size; ++y){
> +for (int x = pad_size; x < width - pad_size; ++x){
> +for (int n_filter = 0; n_filter < conv_params->output_num; 
> ++n_filter){
>  output[n_filter] = conv_params->biases[n_filter];
> -for (ch = 0; ch < conv_params->input_num; ++ch){
> -for (kernel_y = 0; kernel_y < conv_params->kernel_size; 
> ++kernel_y){
> -for (kernel_x = 0; kernel_x < 
> conv_params->kernel_size; ++kernel_x){
> -output[n_filter] += input[CLAMP_TO_EDGE(y + 
> kernel_y - radius, height) * src_linesize +
> -  CLAMP_TO_EDGE(x + 
> kernel_x - radius, width) * conv_params->input_num + ch] *
> -conv_params->kernel[n_filter 
> * filter_size + kernel_y * filter_linesize +
> -kernel_x 
> * conv_params->input_num + ch];
> +
> +for (int ch = 0; ch < conv_params->input_num; ++ch){
> +for (int kernel_y = 0; kernel_y < 
> conv_params->kernel_size; ++kernel_y){
> +for (int kernel_x = 0; kernel_x < 
> conv_params->kernel_size; ++kernel_x){
> +float input_pel;
> +if(conv_params->padding_method == 
> SAME_CLAMP_TO_EDGE){
> +int y_pos = CLAMP_TO_EDGE(y + kernel_y - 
> radius, height);

[FFmpeg-devel] [PATCH v2] Add multiple padding method in dnn native

2019-05-10 Thread Xuewei Meng
---
 libavfilter/dnn_backend_native.c | 52 
 libavfilter/dnn_backend_native.h |  3 ++
 2 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/libavfilter/dnn_backend_native.c b/libavfilter/dnn_backend_native.c
index 06fbdf368b..171a756385 100644
--- a/libavfilter/dnn_backend_native.c
+++ b/libavfilter/dnn_backend_native.c
@@ -61,6 +61,12 @@ static DNNReturnType set_input_output_native(void *model, 
DNNInputData *input, c
 return DNN_ERROR;
 }
 cur_channels = conv_params->output_num;
+
+if(conv_params->padding_method == VALID){
+int pad_size = conv_params->kernel_size - 1;
+cur_height -= pad_size;
+cur_width -= pad_size;
+}
 break;
 case DEPTH_TO_SPACE:
 depth_to_space_params = (DepthToSpaceParams 
*)network->layers[layer].params;
@@ -77,6 +83,10 @@ static DNNReturnType set_input_output_native(void *model, 
DNNInputData *input, c
 if (network->layers[layer].output){
 av_freep(>layers[layer].output);
 }
+
+if(cur_height <= 0 || cur_width <= 0)
+return DNN_ERROR; 
+
 network->layers[layer].output = av_malloc(cur_height * cur_width * 
cur_channels * sizeof(float));
 if (!network->layers[layer].output){
 return DNN_ERROR;
@@ -154,13 +164,14 @@ DNNModel *ff_dnn_load_model_native(const char 
*model_filename)
 ff_dnn_free_model_native();
 return NULL;
 }
+conv_params->padding_method = 
(int32_t)avio_rl32(model_file_context);
 conv_params->activation = (int32_t)avio_rl32(model_file_context);
 conv_params->input_num = (int32_t)avio_rl32(model_file_context);
 conv_params->output_num = (int32_t)avio_rl32(model_file_context);
 conv_params->kernel_size = (int32_t)avio_rl32(model_file_context);
 kernel_size = conv_params->input_num * conv_params->output_num *
   conv_params->kernel_size * conv_params->kernel_size;
-dnn_size += 16 + (kernel_size + conv_params->output_num << 2);
+dnn_size += 20 + (kernel_size + conv_params->output_num << 2);
 if (dnn_size > file_size || conv_params->input_num <= 0 ||
 conv_params->output_num <= 0 || conv_params->kernel_size <= 0){
 avio_closep(_file_context);
@@ -218,23 +229,35 @@ DNNModel *ff_dnn_load_model_native(const char 
*model_filename)
 
 static void convolve(const float *input, float *output, const 
ConvolutionalParams *conv_params, int width, int height)
 {
-int y, x, n_filter, ch, kernel_y, kernel_x;
 int radius = conv_params->kernel_size >> 1;
 int src_linesize = width * conv_params->input_num;
 int filter_linesize = conv_params->kernel_size * conv_params->input_num;
 int filter_size = conv_params->kernel_size * filter_linesize;
+int pad_size = (conv_params->padding_method == VALID) ? 
(conv_params->kernel_size - 1) / 2 : 0;
 
-for (y = 0; y < height; ++y){
-for (x = 0; x < width; ++x){
-for (n_filter = 0; n_filter < conv_params->output_num; ++n_filter){
+for (int y = pad_size; y < height - pad_size; ++y){
+for (int x = pad_size; x < width - pad_size; ++x){
+for (int n_filter = 0; n_filter < conv_params->output_num; 
++n_filter){
 output[n_filter] = conv_params->biases[n_filter];
-for (ch = 0; ch < conv_params->input_num; ++ch){
-for (kernel_y = 0; kernel_y < conv_params->kernel_size; 
++kernel_y){
-for (kernel_x = 0; kernel_x < 
conv_params->kernel_size; ++kernel_x){
-output[n_filter] += input[CLAMP_TO_EDGE(y + 
kernel_y - radius, height) * src_linesize +
-  CLAMP_TO_EDGE(x + 
kernel_x - radius, width) * conv_params->input_num + ch] *
-conv_params->kernel[n_filter * 
filter_size + kernel_y * filter_linesize +
-kernel_x * 
conv_params->input_num + ch];
+
+for (int ch = 0; ch < conv_params->input_num; ++ch){
+for (int kernel_y = 0; kernel_y < 
conv_params->kernel_size; ++kernel_y){
+for (int kernel_x = 0; kernel_x < 
conv_params->kernel_size; ++kernel_x){
+float input_pel;
+if(conv_params->padding_method == 
SAME_CLAMP_TO_EDGE){
+int y_pos = CLAMP_TO_EDGE(y + kernel_y - 
radius, height);
+int x_pos = CLAMP_TO_EDGE(x + kernel_x - 
radius, width);
+input_pel = input[y_pos * src_linesize + x_pos 
* conv_params->input_num + ch];
+}else{
+