blob: b87d0c882c19f0dc39ceef9af7ccbc7c949e79a8
1 | /* |
2 | * Copyright (C) 2017 Amlogic, Inc. All rights reserved. |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
12 | * more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License along |
15 | * with this program; if not, write to the Free Software Foundation, Inc., |
16 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
17 | * |
18 | * Description: |
19 | */ |
20 | #include <linux/types.h> |
21 | #include <linux/amlogic/media/utils/amstream.h> |
22 | #include <linux/amlogic/media/utils/vformat.h> |
23 | #include <linux/amlogic/media/utils/aformat.h> |
24 | #include <linux/amlogic/media/frame_sync/tsync.h> |
25 | #include <linux/amlogic/media/frame_sync/ptsserv.h> |
26 | #include <linux/amlogic/media/frame_sync/timestamp.h> |
27 | #include <linux/amlogic/media/utils/amports_config.h> |
28 | #include <linux/amlogic/media/frame_sync/tsync_pcr.h> |
29 | #include <linux/amlogic/media/codec_mm/codec_mm.h> |
30 | #include <linux/amlogic/media/codec_mm/configs.h> |
31 | #include <linux/amlogic/media/utils/vformat.h> |
32 | #include <linux/amlogic/media/utils/aformat.h> |
33 | #include <linux/amlogic/media/registers/register.h> |
34 | #include "../stream_input/amports/adec.h" |
35 | #include "../stream_input/parser/streambuf.h" |
36 | #include "../stream_input/parser/streambuf_reg.h" |
37 | #include "../stream_input/parser/tsdemux.h" |
38 | #include "../stream_input/parser/psparser.h" |
39 | #include "../stream_input/parser/esparser.h" |
40 | #include "../frame_provider/decoder/utils/vdec.h" |
41 | #include "../common/media_clock/switch/amports_gate.h" |
42 | #include <linux/delay.h> |
43 | #include "aml_vcodec_adapt.h" |
44 | #include <linux/crc32.h> |
45 | |
46 | #define DEFAULT_VIDEO_BUFFER_SIZE (1024 * 1024 * 3) |
47 | #define DEFAULT_VIDEO_BUFFER_SIZE_4K (1024 * 1024 * 6) |
48 | #define DEFAULT_VIDEO_BUFFER_SIZE_TVP (1024 * 1024 * 10) |
49 | #define DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP (1024 * 1024 * 15) |
50 | #define DEFAULT_AUDIO_BUFFER_SIZE (1024*768*2) |
51 | #define DEFAULT_SUBTITLE_BUFFER_SIZE (1024*256) |
52 | |
53 | #define PTS_OUTSIDE (1) |
54 | #define SYNC_OUTSIDE (2) |
55 | |
56 | //#define DATA_DEBUG |
57 | |
58 | static int def_4k_vstreambuf_sizeM = |
59 | (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); |
60 | static int def_vstreambuf_sizeM = |
61 | (DEFAULT_VIDEO_BUFFER_SIZE >> 20); |
62 | |
63 | static int slow_input = 0; |
64 | |
65 | static int use_bufferlevelx10000 = 10000; |
66 | static unsigned int amstream_buf_num = BUF_MAX_NUM; |
67 | |
68 | static struct stream_buf_s bufs[BUF_MAX_NUM] = { |
69 | { |
70 | .reg_base = VLD_MEM_VIFIFO_REG_BASE, |
71 | .type = BUF_TYPE_VIDEO, |
72 | .buf_start = 0, |
73 | .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, |
74 | .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, |
75 | .first_tstamp = INVALID_PTS |
76 | }, |
77 | { |
78 | .reg_base = AIU_MEM_AIFIFO_REG_BASE, |
79 | .type = BUF_TYPE_AUDIO, |
80 | .buf_start = 0, |
81 | .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, |
82 | .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, |
83 | .first_tstamp = INVALID_PTS |
84 | }, |
85 | { |
86 | .reg_base = 0, |
87 | .type = BUF_TYPE_SUBTITLE, |
88 | .buf_start = 0, |
89 | .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, |
90 | .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, |
91 | .first_tstamp = INVALID_PTS |
92 | }, |
93 | { |
94 | .reg_base = 0, |
95 | .type = BUF_TYPE_USERDATA, |
96 | .buf_start = 0, |
97 | .buf_size = 0, |
98 | .first_tstamp = INVALID_PTS |
99 | }, |
100 | { |
101 | .reg_base = HEVC_STREAM_REG_BASE, |
102 | .type = BUF_TYPE_HEVC, |
103 | .buf_start = 0, |
104 | .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, |
105 | .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, |
106 | .first_tstamp = INVALID_PTS |
107 | }, |
108 | }; |
109 | |
110 | extern int aml_set_vfm_path, aml_set_vdec_type; |
111 | extern bool aml_set_vfm_enable, aml_set_vdec_type_enable; |
112 | |
113 | static void set_default_params(struct aml_vdec_adapt *vdec) |
114 | { |
115 | ulong sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE); |
116 | |
117 | vdec->dec_prop.param = (void *)sync_mode; |
118 | vdec->dec_prop.format = vdec->format; |
119 | vdec->dec_prop.width = 1920; |
120 | vdec->dec_prop.height = 1088; |
121 | vdec->dec_prop.rate = 3200; |
122 | } |
123 | |
124 | static int enable_hardware(struct stream_port_s *port) |
125 | { |
126 | if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) |
127 | return -1; |
128 | |
129 | amports_switch_gate("demux", 1); |
130 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) |
131 | amports_switch_gate("parser_top", 1); |
132 | |
133 | if (port->type & PORT_TYPE_VIDEO) { |
134 | amports_switch_gate("vdec", 1); |
135 | |
136 | if (has_hevc_vdec()) { |
137 | if (port->type & PORT_TYPE_HEVC) |
138 | vdec_poweron(VDEC_HEVC); |
139 | else |
140 | vdec_poweron(VDEC_1); |
141 | } else { |
142 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) |
143 | vdec_poweron(VDEC_1); |
144 | } |
145 | } |
146 | |
147 | return 0; |
148 | } |
149 | |
150 | static int disable_hardware(struct stream_port_s *port) |
151 | { |
152 | if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6) |
153 | return -1; |
154 | |
155 | if (port->type & PORT_TYPE_VIDEO) { |
156 | if (has_hevc_vdec()) { |
157 | if (port->type & PORT_TYPE_HEVC) |
158 | vdec_poweroff(VDEC_HEVC); |
159 | else |
160 | vdec_poweroff(VDEC_1); |
161 | } |
162 | |
163 | amports_switch_gate("vdec", 0); |
164 | } |
165 | |
166 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) |
167 | amports_switch_gate("parser_top", 0); |
168 | |
169 | amports_switch_gate("demux", 0); |
170 | |
171 | return 0; |
172 | } |
173 | |
174 | static int reset_canuse_buferlevel(int levelx10000) |
175 | { |
176 | int i; |
177 | struct stream_buf_s *p = NULL; |
178 | |
179 | if (levelx10000 >= 0 && levelx10000 <= 10000) |
180 | use_bufferlevelx10000 = levelx10000; |
181 | else |
182 | use_bufferlevelx10000 = 10000; |
183 | for (i = 0; i < amstream_buf_num; i++) { |
184 | p = &bufs[i]; |
185 | p->canusebuf_size = ((p->buf_size / 1024) * |
186 | use_bufferlevelx10000 / 10000) * 1024; |
187 | p->canusebuf_size += 1023; |
188 | p->canusebuf_size &= ~1023; |
189 | |
190 | if (p->canusebuf_size > p->buf_size) |
191 | p->canusebuf_size = p->buf_size; |
192 | } |
193 | |
194 | return 0; |
195 | } |
196 | |
197 | static void change_vbufsize(struct vdec_s *vdec, |
198 | struct stream_buf_s *pvbuf) |
199 | { |
200 | if (pvbuf->buf_start != 0) { |
201 | v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "streambuf is alloced before\n"); |
202 | return; |
203 | } |
204 | |
205 | if (pvbuf->for_4k) { |
206 | pvbuf->buf_size = def_4k_vstreambuf_sizeM * SZ_1M; |
207 | |
208 | if (vdec->port_flag & PORT_FLAG_DRM) |
209 | pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K_TVP; |
210 | |
211 | if ((pvbuf->buf_size > 30 * SZ_1M) |
212 | && (codec_mm_get_total_size() < 220 * SZ_1M)) { |
213 | /*if less than 250M, used 20M for 4K & 265*/ |
214 | pvbuf->buf_size = pvbuf->buf_size >> 1; |
215 | } |
216 | } else if (pvbuf->buf_size > def_vstreambuf_sizeM * SZ_1M) { |
217 | if (vdec->port_flag & PORT_FLAG_DRM) |
218 | pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; |
219 | } else { |
220 | pvbuf->buf_size = def_vstreambuf_sizeM * SZ_1M; |
221 | if (vdec->port_flag & PORT_FLAG_DRM) |
222 | pvbuf->buf_size = DEFAULT_VIDEO_BUFFER_SIZE_TVP; |
223 | } |
224 | |
225 | reset_canuse_buferlevel(10000); |
226 | } |
227 | |
228 | static void user_buffer_init(void) |
229 | { |
230 | struct stream_buf_s *pubuf = &bufs[BUF_TYPE_USERDATA]; |
231 | |
232 | pubuf->buf_size = 0; |
233 | pubuf->buf_start = 0; |
234 | pubuf->buf_wp = 0; |
235 | pubuf->buf_rp = 0; |
236 | } |
237 | |
238 | static void audio_component_release(struct stream_port_s *port, |
239 | struct stream_buf_s *pbuf, int release_num) |
240 | { |
241 | switch (release_num) { |
242 | default: |
243 | case 0: |
244 | case 4: |
245 | esparser_release(pbuf); |
246 | case 3: |
247 | adec_release(port->vformat); |
248 | case 2: |
249 | stbuf_release(pbuf, false); |
250 | case 1: |
251 | ; |
252 | } |
253 | } |
254 | |
255 | static int audio_component_init(struct stream_port_s *port, |
256 | struct stream_buf_s *pbuf) |
257 | { |
258 | int r; |
259 | |
260 | if ((port->flag & PORT_FLAG_AFORMAT) == 0) { |
261 | v4l_dbg(0, V4L_DEBUG_CODEC_ERROR, "aformat not set\n"); |
262 | return 0; |
263 | } |
264 | |
265 | r = stbuf_init(pbuf, NULL, false); |
266 | if (r < 0) |
267 | return r; |
268 | |
269 | r = adec_init(port); |
270 | if (r < 0) { |
271 | audio_component_release(port, pbuf, 2); |
272 | return r; |
273 | } |
274 | |
275 | if (port->type & PORT_TYPE_ES) { |
276 | r = esparser_init(pbuf, NULL); |
277 | if (r < 0) { |
278 | audio_component_release(port, pbuf, 3); |
279 | return r; |
280 | } |
281 | } |
282 | |
283 | pbuf->flag |= BUF_FLAG_IN_USE; |
284 | |
285 | return 0; |
286 | } |
287 | |
288 | static void video_component_release(struct stream_port_s *port, |
289 | struct stream_buf_s *pbuf, int release_num) |
290 | { |
291 | struct aml_vdec_adapt *ada_ctx |
292 | = container_of(port, struct aml_vdec_adapt, port); |
293 | struct vdec_s *vdec = ada_ctx->vdec; |
294 | |
295 | struct vdec_s *slave = NULL; |
296 | bool is_multidec = !vdec_single(vdec); |
297 | |
298 | switch (release_num) { |
299 | default: |
300 | case 0: |
301 | case 4: { |
302 | if ((port->type & PORT_TYPE_FRAME) == 0) |
303 | esparser_release(pbuf); |
304 | } |
305 | |
306 | case 3: { |
307 | if (vdec->slave) |
308 | slave = vdec->slave; |
309 | vdec_release(vdec); |
310 | |
311 | if (slave) |
312 | vdec_release(slave); |
313 | vdec = NULL; |
314 | } |
315 | |
316 | case 2: { |
317 | if ((port->type & PORT_TYPE_FRAME) == 0) |
318 | stbuf_release(pbuf, is_multidec); |
319 | } |
320 | |
321 | case 1: |
322 | ; |
323 | } |
324 | } |
325 | |
326 | static int video_component_init(struct stream_port_s *port, |
327 | struct stream_buf_s *pbuf) |
328 | { |
329 | int ret = -1; |
330 | struct aml_vdec_adapt *ada_ctx |
331 | = container_of(port, struct aml_vdec_adapt, port); |
332 | struct vdec_s *vdec = ada_ctx->vdec; |
333 | |
334 | if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) { |
335 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vformat not set\n"); |
336 | return -EPERM; |
337 | } |
338 | |
339 | if ((vdec->sys_info->height * vdec->sys_info->width) > 1920 * 1088 |
340 | || port->vformat == VFORMAT_H264_4K2K) { |
341 | pbuf->for_4k = 1; |
342 | if (get_cpu_type() >= MESON_CPU_MAJOR_ID_TXLX |
343 | && port->vformat == VFORMAT_H264) |
344 | vdec_poweron(VDEC_HEVC); |
345 | } else |
346 | pbuf->for_4k = 0; |
347 | |
348 | if (port->type & PORT_TYPE_FRAME) { |
349 | ret = vdec_init(vdec, pbuf->for_4k); |
350 | if (ret < 0) { |
351 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "failed\n"); |
352 | video_component_release(port, pbuf, 2); |
353 | return ret; |
354 | } |
355 | |
356 | return 0; |
357 | } |
358 | |
359 | change_vbufsize(vdec, pbuf); |
360 | |
361 | if (has_hevc_vdec()) { |
362 | if (port->type & PORT_TYPE_MPTS) { |
363 | if (pbuf->type == BUF_TYPE_HEVC) |
364 | vdec_poweroff(VDEC_1); |
365 | else |
366 | vdec_poweroff(VDEC_HEVC); |
367 | } |
368 | } |
369 | |
370 | ret = stbuf_init(pbuf, vdec, false); |
371 | if (ret < 0) { |
372 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "stbuf_init failed\n"); |
373 | return ret; |
374 | } |
375 | |
376 | /* todo: set path based on port flag */ |
377 | ret = vdec_init(vdec, pbuf->for_4k); |
378 | if (ret < 0) { |
379 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n"); |
380 | video_component_release(port, pbuf, 2); |
381 | return ret; |
382 | } |
383 | |
384 | if (vdec_dual(vdec)) { |
385 | ret = vdec_init(vdec->slave, pbuf->for_4k); |
386 | if (ret < 0) { |
387 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "vdec_init failed\n"); |
388 | video_component_release(port, pbuf, 2); |
389 | return ret; |
390 | } |
391 | } |
392 | |
393 | if (port->type & PORT_TYPE_ES) { |
394 | ret = esparser_init(pbuf, vdec); |
395 | if (ret < 0) { |
396 | video_component_release(port, pbuf, 3); |
397 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "esparser_init() failed\n"); |
398 | return ret; |
399 | } |
400 | } |
401 | |
402 | pbuf->flag |= BUF_FLAG_IN_USE; |
403 | |
404 | vdec_connect(vdec); |
405 | |
406 | return 0; |
407 | } |
408 | |
409 | static int vdec_ports_release(struct stream_port_s *port) |
410 | { |
411 | struct aml_vdec_adapt *ada_ctx |
412 | = container_of(port, struct aml_vdec_adapt, port); |
413 | struct vdec_s *vdec = ada_ctx->vdec; |
414 | |
415 | struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; |
416 | struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; |
417 | //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; |
418 | struct vdec_s *slave = NULL; |
419 | |
420 | if (has_hevc_vdec()) { |
421 | if (port->vformat == VFORMAT_HEVC |
422 | || port->vformat == VFORMAT_VP9) |
423 | pvbuf = &bufs[BUF_TYPE_HEVC]; |
424 | } |
425 | |
426 | if (port->type & PORT_TYPE_MPTS) { |
427 | tsync_pcr_stop(); |
428 | tsdemux_release(); |
429 | } |
430 | |
431 | if (port->type & PORT_TYPE_MPPS) |
432 | psparser_release(); |
433 | |
434 | if (port->type & PORT_TYPE_VIDEO) |
435 | video_component_release(port, pvbuf, 0); |
436 | |
437 | if (port->type & PORT_TYPE_AUDIO) |
438 | audio_component_release(port, pabuf, 0); |
439 | |
440 | if (port->type & PORT_TYPE_SUB) |
441 | //sub_port_release(port, psbuf); |
442 | |
443 | if (vdec) { |
444 | if (vdec->slave) |
445 | slave = vdec->slave; |
446 | |
447 | vdec_release(vdec); |
448 | |
449 | if (slave) |
450 | vdec_release(slave); |
451 | vdec = NULL; |
452 | } |
453 | |
454 | port->pcr_inited = 0; |
455 | port->flag = 0; |
456 | |
457 | return 0; |
458 | } |
459 | |
460 | static void set_vdec_properity(struct vdec_s *vdec, |
461 | struct aml_vdec_adapt *ada_ctx) |
462 | { |
463 | vdec->sys_info = &ada_ctx->dec_prop; |
464 | vdec->port = &ada_ctx->port; |
465 | vdec->format = ada_ctx->video_type; |
466 | vdec->sys_info_store = ada_ctx->dec_prop; |
467 | vdec->vf_receiver_name = ada_ctx->recv_name; |
468 | |
469 | /* binding v4l2 ctx to vdec. */ |
470 | vdec->private = ada_ctx->ctx; |
471 | |
472 | /* set video format, sys info and vfm map.*/ |
473 | vdec->port->vformat = vdec->format; |
474 | vdec->port->type |= PORT_TYPE_VIDEO; |
475 | vdec->port_flag |= (vdec->port->flag | PORT_FLAG_VFORMAT); |
476 | if (vdec->slave) { |
477 | vdec->slave->format = ada_ctx->dec_prop.format; |
478 | vdec->slave->port_flag |= PORT_FLAG_VFORMAT; |
479 | } |
480 | |
481 | vdec->type = VDEC_TYPE_FRAME_BLOCK; |
482 | vdec->port->type |= PORT_TYPE_FRAME; |
483 | vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_OSD; |
484 | |
485 | if (aml_set_vdec_type_enable) { |
486 | if (aml_set_vdec_type == VDEC_TYPE_STREAM_PARSER) { |
487 | vdec->type = VDEC_TYPE_STREAM_PARSER; |
488 | vdec->port->type &= ~PORT_TYPE_FRAME; |
489 | vdec->port->type |= PORT_TYPE_ES; |
490 | } else if (aml_set_vdec_type == VDEC_TYPE_FRAME_BLOCK) { |
491 | vdec->type = VDEC_TYPE_FRAME_BLOCK; |
492 | vdec->port->type &= ~PORT_TYPE_ES; |
493 | vdec->port->type |= PORT_TYPE_FRAME; |
494 | } |
495 | } |
496 | |
497 | if (aml_set_vfm_enable) |
498 | vdec->frame_base_video_path = aml_set_vfm_path; |
499 | |
500 | vdec->port->flag = vdec->port_flag; |
501 | ada_ctx->vfm_path = vdec->frame_base_video_path; |
502 | |
503 | vdec->config_len = ada_ctx->config.length > |
504 | PAGE_SIZE ? PAGE_SIZE : ada_ctx->config.length; |
505 | memcpy(vdec->config, ada_ctx->config.buf, vdec->config_len); |
506 | |
507 | ada_ctx->vdec = vdec; |
508 | } |
509 | |
510 | static int vdec_ports_init(struct aml_vdec_adapt *ada_ctx) |
511 | { |
512 | int ret = -1; |
513 | struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; |
514 | struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; |
515 | //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; |
516 | struct vdec_s *vdec = NULL; |
517 | |
518 | /* create the vdec instance.*/ |
519 | vdec = vdec_create(&ada_ctx->port, NULL); |
520 | if (IS_ERR_OR_NULL(vdec)) |
521 | return -1; |
522 | |
523 | set_vdec_properity(vdec, ada_ctx); |
524 | |
525 | /* init hw and gate*/ |
526 | ret = enable_hardware(vdec->port); |
527 | if (ret < 0) { |
528 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "enable hw fail.\n"); |
529 | goto error1; |
530 | } |
531 | |
532 | stbuf_fetch_init(); |
533 | user_buffer_init(); |
534 | |
535 | if ((vdec->port->type & PORT_TYPE_AUDIO) |
536 | && (vdec->port_flag & PORT_FLAG_AFORMAT)) { |
537 | ret = audio_component_init(vdec->port, pabuf); |
538 | if (ret < 0) { |
539 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "audio_component_init failed\n"); |
540 | goto error1; |
541 | } |
542 | } |
543 | |
544 | if ((vdec->port->type & PORT_TYPE_VIDEO) |
545 | && (vdec->port_flag & PORT_FLAG_VFORMAT)) { |
546 | pvbuf->for_4k = 0; |
547 | if (has_hevc_vdec()) { |
548 | if (vdec->port->vformat == VFORMAT_HEVC |
549 | || vdec->port->vformat == VFORMAT_VP9) |
550 | pvbuf = &bufs[BUF_TYPE_HEVC]; |
551 | } |
552 | |
553 | ret = video_component_init(vdec->port, pvbuf); |
554 | if (ret < 0) { |
555 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_ERROR, "video_component_init failed\n"); |
556 | goto error2; |
557 | } |
558 | |
559 | /* connect vdec at the end after all HW initialization */ |
560 | vdec_connect(vdec); |
561 | } |
562 | |
563 | return 0; |
564 | |
565 | //error3: |
566 | //video_component_release(port, pvbuf, 0); |
567 | error2: |
568 | audio_component_release(vdec->port, pabuf, 0); |
569 | error1: |
570 | return ret; |
571 | } |
572 | |
573 | int video_decoder_init(struct aml_vdec_adapt *vdec) |
574 | { |
575 | int ret = -1; |
576 | |
577 | /* sets configure data */ |
578 | set_default_params(vdec); |
579 | |
580 | /* init the buffer work space and connect vdec.*/ |
581 | ret = vdec_ports_init(vdec); |
582 | if (ret < 0) { |
583 | v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR, "vdec ports init fail.\n"); |
584 | goto out; |
585 | } |
586 | out: |
587 | return ret; |
588 | } |
589 | |
590 | int video_decoder_release(struct aml_vdec_adapt *vdec) |
591 | { |
592 | int ret = -1; |
593 | struct stream_port_s *port = &vdec->port; |
594 | |
595 | ret = vdec_ports_release(port); |
596 | if (ret < 0) { |
597 | v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR, "vdec ports release fail.\n"); |
598 | goto out; |
599 | } |
600 | |
601 | /* disable gates */ |
602 | ret = disable_hardware(port); |
603 | if (ret < 0) { |
604 | v4l_dbg(vdec->ctx, V4L_DEBUG_CODEC_ERROR, "disable hw fail.\n"); |
605 | goto out; |
606 | } |
607 | out: |
608 | return ret; |
609 | } |
610 | |
611 | int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, |
612 | const char *buf, unsigned int count) |
613 | { |
614 | int ret = -1; |
615 | int try_cnt = 100; |
616 | struct stream_port_s *port = &ada_ctx->port; |
617 | struct vdec_s *vdec = ada_ctx->vdec; |
618 | struct stream_buf_s *pbuf = NULL; |
619 | |
620 | if (has_hevc_vdec()) { |
621 | pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : |
622 | &bufs[BUF_TYPE_VIDEO]; |
623 | } else |
624 | pbuf = &bufs[BUF_TYPE_VIDEO]; |
625 | |
626 | /*if (!(port_get_inited(priv))) { |
627 | r = video_decoder_init(priv); |
628 | if (r < 0) |
629 | return r; |
630 | }*/ |
631 | |
632 | do { |
633 | if (vdec->port_flag & PORT_FLAG_DRM) |
634 | ret = drm_write(ada_ctx->filp, pbuf, buf, count); |
635 | else |
636 | ret = esparser_write(ada_ctx->filp, pbuf, buf, count); |
637 | |
638 | if (ret == -EAGAIN) |
639 | msleep(30); |
640 | } while (ret == -EAGAIN && try_cnt--); |
641 | |
642 | if (slow_input) { |
643 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, |
644 | "slow_input: es codec write size %x\n", ret); |
645 | msleep(10); |
646 | } |
647 | |
648 | #ifdef DATA_DEBUG |
649 | /* dump to file */ |
650 | //dump_write(vbuf, size); |
651 | //v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, "vbuf: %p, size: %u, ret: %d\n", vbuf, size, ret); |
652 | #endif |
653 | |
654 | return ret; |
655 | } |
656 | |
657 | bool vdec_input_full(struct aml_vdec_adapt *ada_ctx) |
658 | { |
659 | struct vdec_s *vdec = ada_ctx->vdec; |
660 | |
661 | return (vdec->input.have_frame_num > 600) ? true : false; |
662 | } |
663 | |
664 | int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, |
665 | const char *buf, unsigned int count, u64 timestamp) |
666 | { |
667 | int ret = -1; |
668 | struct vdec_s *vdec = ada_ctx->vdec; |
669 | |
670 | /* set timestamp */ |
671 | vdec_set_timestamp(vdec, timestamp); |
672 | |
673 | ret = vdec_write_vframe(vdec, buf, count); |
674 | |
675 | if (slow_input) { |
676 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, |
677 | "slow_input: frame codec write size %d\n", ret); |
678 | msleep(30); |
679 | } |
680 | |
681 | #ifdef DATA_DEBUG |
682 | /* dump to file */ |
683 | dump_write(buf, count); |
684 | #endif |
685 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT, |
686 | "write frames, vbuf: %p, size: %u, ret: %d, crc: %x\n", |
687 | buf, count, ret, crc32_le(0, buf, count)); |
688 | |
689 | return ret; |
690 | } |
691 | |
692 | int vdec_vframe_write_with_dma(struct aml_vdec_adapt *ada_ctx, |
693 | ulong addr, u32 count, u64 timestamp, u32 handle) |
694 | { |
695 | int ret = -1; |
696 | struct vdec_s *vdec = ada_ctx->vdec; |
697 | |
698 | /* set timestamp */ |
699 | vdec_set_timestamp(vdec, timestamp); |
700 | |
701 | ret = vdec_write_vframe_with_dma(vdec, addr, count, handle); |
702 | |
703 | if (slow_input) { |
704 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, |
705 | "slow_input: frame codec write size %d\n", ret); |
706 | msleep(30); |
707 | } |
708 | |
709 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_INPUT, |
710 | "write frames, vbuf: %lx, size: %u, ret: %d\n", |
711 | addr, count, ret); |
712 | |
713 | return ret; |
714 | } |
715 | |
716 | void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) |
717 | { |
718 | struct vdec_s *vdec = ada_ctx->vdec; |
719 | |
720 | if (vdec) |
721 | vdec_set_eos(vdec, true); |
722 | } |
723 | |
724 | int aml_codec_reset(struct aml_vdec_adapt *ada_ctx, int *mode) |
725 | { |
726 | struct vdec_s *vdec = ada_ctx->vdec; |
727 | int ret = 0; |
728 | |
729 | if (vdec) { |
730 | if (!ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed) |
731 | vdec_set_eos(vdec, false); |
732 | if (*mode == V4L_RESET_MODE_NORMAL && |
733 | vdec->input.have_frame_num == 0) { |
734 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, |
735 | "no input reset mode: %d\n", *mode); |
736 | *mode = V4L_RESET_MODE_LIGHT; |
737 | } |
738 | if (ada_ctx->ctx->param_sets_from_ucode && |
739 | *mode == V4L_RESET_MODE_NORMAL && |
740 | ada_ctx->ctx->q_data[AML_Q_DATA_SRC].resolution_changed == true) { |
741 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, |
742 | "resolution_changed reset mode: %d\n", *mode); |
743 | *mode = V4L_RESET_MODE_LIGHT; |
744 | } |
745 | v4l_dbg(ada_ctx->ctx, V4L_DEBUG_CODEC_PRINFO, |
746 | "reset mode: %d\n", *mode); |
747 | |
748 | ret = vdec_v4l2_reset(vdec, *mode); |
749 | *mode = V4L_RESET_MODE_NORMAL; |
750 | } |
751 | |
752 | return ret; |
753 | } |
754 | |
755 | bool is_input_ready(struct aml_vdec_adapt *ada_ctx) |
756 | { |
757 | struct vdec_s *vdec = ada_ctx->vdec; |
758 | int state = VDEC_STATUS_UNINITIALIZED; |
759 | |
760 | if (vdec) { |
761 | state = vdec_get_status(vdec); |
762 | |
763 | if (state == VDEC_STATUS_CONNECTED |
764 | || state == VDEC_STATUS_ACTIVE) |
765 | return true; |
766 | } |
767 | |
768 | return false; |
769 | } |
770 | |
771 | int vdec_frame_number(struct aml_vdec_adapt *ada_ctx) |
772 | { |
773 | struct vdec_s *vdec = ada_ctx->vdec; |
774 | |
775 | if (vdec) |
776 | return vdec_get_frame_num(vdec); |
777 | else |
778 | return -1; |
779 | } |
780 | |
781 | void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len) |
782 | { |
783 | struct vdec_s *vdec = ada_ctx->vdec; |
784 | |
785 | vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len; |
786 | memcpy(vdec->config, data, vdec->config_len); |
787 | } |
788 | |
789 | u32 aml_recycle_buffer(struct aml_vdec_adapt *adaptor) |
790 | { |
791 | return vdec_input_get_freed_handle(adaptor->vdec); |
792 | } |
793 | |
794 |