]> git.sesse.net Git - ffmpeg/blob - libavfilter/dnn/dnn_io_proc.c
dnn: add NV12 pixel format support
[ffmpeg] / libavfilter / dnn / dnn_io_proc.c
1 /*
2  * Copyright (c) 2020
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "dnn_io_proc.h"
22 #include "libavutil/imgutils.h"
23 #include "libswscale/swscale.h"
24
25 DNNReturnType proc_from_dnn_to_frame(AVFrame *frame, DNNData *output, void *log_ctx)
26 {
27     struct SwsContext *sws_ctx;
28     int bytewidth = av_image_get_linesize(frame->format, frame->width, 0);
29     if (output->dt != DNN_FLOAT) {
30         av_log(log_ctx, AV_LOG_ERROR, "do not support data type rather than DNN_FLOAT\n");
31         return DNN_ERROR;
32     }
33
34     switch (frame->format) {
35     case AV_PIX_FMT_RGB24:
36     case AV_PIX_FMT_BGR24:
37         sws_ctx = sws_getContext(frame->width * 3,
38                                  frame->height,
39                                  AV_PIX_FMT_GRAYF32,
40                                  frame->width * 3,
41                                  frame->height,
42                                  AV_PIX_FMT_GRAY8,
43                                  0, NULL, NULL, NULL);
44         if (!sws_ctx) {
45             av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion "
46                 "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
47                 av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32), frame->width * 3, frame->height,
48                 av_get_pix_fmt_name(AV_PIX_FMT_GRAY8),   frame->width * 3, frame->height);
49             return DNN_ERROR;
50         }
51         sws_scale(sws_ctx, (const uint8_t *[4]){(const uint8_t *)output->data, 0, 0, 0},
52                            (const int[4]){frame->width * 3 * sizeof(float), 0, 0, 0}, 0, frame->height,
53                            (uint8_t * const*)frame->data, frame->linesize);
54         sws_freeContext(sws_ctx);
55         return DNN_SUCCESS;
56     case AV_PIX_FMT_GRAYF32:
57         av_image_copy_plane(frame->data[0], frame->linesize[0],
58                             output->data, bytewidth,
59                             bytewidth, frame->height);
60         return DNN_SUCCESS;
61     case AV_PIX_FMT_YUV420P:
62     case AV_PIX_FMT_YUV422P:
63     case AV_PIX_FMT_YUV444P:
64     case AV_PIX_FMT_YUV410P:
65     case AV_PIX_FMT_YUV411P:
66     case AV_PIX_FMT_GRAY8:
67     case AV_PIX_FMT_NV12:
68         sws_ctx = sws_getContext(frame->width,
69                                  frame->height,
70                                  AV_PIX_FMT_GRAYF32,
71                                  frame->width,
72                                  frame->height,
73                                  AV_PIX_FMT_GRAY8,
74                                  0, NULL, NULL, NULL);
75         if (!sws_ctx) {
76             av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion "
77                 "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
78                 av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32), frame->width, frame->height,
79                 av_get_pix_fmt_name(AV_PIX_FMT_GRAY8),   frame->width, frame->height);
80             return DNN_ERROR;
81         }
82         sws_scale(sws_ctx, (const uint8_t *[4]){(const uint8_t *)output->data, 0, 0, 0},
83                            (const int[4]){frame->width * sizeof(float), 0, 0, 0}, 0, frame->height,
84                            (uint8_t * const*)frame->data, frame->linesize);
85         sws_freeContext(sws_ctx);
86         return DNN_SUCCESS;
87     default:
88         av_log(log_ctx, AV_LOG_ERROR, "do not support frame format %s\n",
89                av_get_pix_fmt_name(frame->format));
90         return DNN_ERROR;
91     }
92
93     return DNN_SUCCESS;
94 }
95
96 DNNReturnType proc_from_frame_to_dnn(AVFrame *frame, DNNData *input, void *log_ctx)
97 {
98     struct SwsContext *sws_ctx;
99     int bytewidth = av_image_get_linesize(frame->format, frame->width, 0);
100     if (input->dt != DNN_FLOAT) {
101         av_log(log_ctx, AV_LOG_ERROR, "do not support data type rather than DNN_FLOAT\n");
102         return DNN_ERROR;
103     }
104
105     switch (frame->format) {
106     case AV_PIX_FMT_RGB24:
107     case AV_PIX_FMT_BGR24:
108         sws_ctx = sws_getContext(frame->width * 3,
109                                  frame->height,
110                                  AV_PIX_FMT_GRAY8,
111                                  frame->width * 3,
112                                  frame->height,
113                                  AV_PIX_FMT_GRAYF32,
114                                  0, NULL, NULL, NULL);
115         if (!sws_ctx) {
116             av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion "
117                 "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
118                 av_get_pix_fmt_name(AV_PIX_FMT_GRAY8),  frame->width * 3, frame->height,
119                 av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32),frame->width * 3, frame->height);
120             return DNN_ERROR;
121         }
122         sws_scale(sws_ctx, (const uint8_t **)frame->data,
123                            frame->linesize, 0, frame->height,
124                            (uint8_t * const*)(&input->data),
125                            (const int [4]){frame->width * 3 * sizeof(float), 0, 0, 0});
126         sws_freeContext(sws_ctx);
127         break;
128     case AV_PIX_FMT_GRAYF32:
129         av_image_copy_plane(input->data, bytewidth,
130                             frame->data[0], frame->linesize[0],
131                             bytewidth, frame->height);
132         break;
133     case AV_PIX_FMT_YUV420P:
134     case AV_PIX_FMT_YUV422P:
135     case AV_PIX_FMT_YUV444P:
136     case AV_PIX_FMT_YUV410P:
137     case AV_PIX_FMT_YUV411P:
138     case AV_PIX_FMT_GRAY8:
139     case AV_PIX_FMT_NV12:
140         sws_ctx = sws_getContext(frame->width,
141                                  frame->height,
142                                  AV_PIX_FMT_GRAY8,
143                                  frame->width,
144                                  frame->height,
145                                  AV_PIX_FMT_GRAYF32,
146                                  0, NULL, NULL, NULL);
147         if (!sws_ctx) {
148             av_log(log_ctx, AV_LOG_ERROR, "Impossible to create scale context for the conversion "
149                 "fmt:%s s:%dx%d -> fmt:%s s:%dx%d\n",
150                 av_get_pix_fmt_name(AV_PIX_FMT_GRAY8),  frame->width, frame->height,
151                 av_get_pix_fmt_name(AV_PIX_FMT_GRAYF32),frame->width, frame->height);
152             return DNN_ERROR;
153         }
154         sws_scale(sws_ctx, (const uint8_t **)frame->data,
155                            frame->linesize, 0, frame->height,
156                            (uint8_t * const*)(&input->data),
157                            (const int [4]){frame->width * sizeof(float), 0, 0, 0});
158         sws_freeContext(sws_ctx);
159         break;
160     default:
161         av_log(log_ctx, AV_LOG_ERROR, "do not support frame format %s\n",
162                av_get_pix_fmt_name(frame->format));
163         return DNN_ERROR;
164     }
165
166     return DNN_SUCCESS;
167 }