blob: b596d4d555ba19074eda50a56a50d00b7a4cfa4e
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 | #define USE_V4L_PORTS (0x80) |
56 | |
57 | #define DATA_DEBUG |
58 | |
59 | static int def_4k_vstreambuf_sizeM = |
60 | (DEFAULT_VIDEO_BUFFER_SIZE_4K >> 20); |
61 | static int def_vstreambuf_sizeM = |
62 | (DEFAULT_VIDEO_BUFFER_SIZE >> 20); |
63 | |
64 | static int slow_input = 0; |
65 | |
66 | static int use_bufferlevelx10000 = 10000; |
67 | static unsigned int amstream_buf_num = BUF_MAX_NUM; |
68 | |
69 | static struct stream_buf_s bufs[BUF_MAX_NUM] = { |
70 | { |
71 | .reg_base = VLD_MEM_VIFIFO_REG_BASE, |
72 | .type = BUF_TYPE_VIDEO, |
73 | .buf_start = 0, |
74 | .buf_size = DEFAULT_VIDEO_BUFFER_SIZE, |
75 | .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE, |
76 | .first_tstamp = INVALID_PTS |
77 | }, |
78 | { |
79 | .reg_base = AIU_MEM_AIFIFO_REG_BASE, |
80 | .type = BUF_TYPE_AUDIO, |
81 | .buf_start = 0, |
82 | .buf_size = DEFAULT_AUDIO_BUFFER_SIZE, |
83 | .default_buf_size = DEFAULT_AUDIO_BUFFER_SIZE, |
84 | .first_tstamp = INVALID_PTS |
85 | }, |
86 | { |
87 | .reg_base = 0, |
88 | .type = BUF_TYPE_SUBTITLE, |
89 | .buf_start = 0, |
90 | .buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, |
91 | .default_buf_size = DEFAULT_SUBTITLE_BUFFER_SIZE, |
92 | .first_tstamp = INVALID_PTS |
93 | }, |
94 | { |
95 | .reg_base = 0, |
96 | .type = BUF_TYPE_USERDATA, |
97 | .buf_start = 0, |
98 | .buf_size = 0, |
99 | .first_tstamp = INVALID_PTS |
100 | }, |
101 | { |
102 | .reg_base = HEVC_STREAM_REG_BASE, |
103 | .type = BUF_TYPE_HEVC, |
104 | .buf_start = 0, |
105 | .buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, |
106 | .default_buf_size = DEFAULT_VIDEO_BUFFER_SIZE_4K, |
107 | .first_tstamp = INVALID_PTS |
108 | }, |
109 | }; |
110 | |
111 | extern int aml_set_vfm_path, aml_set_vdec_type; |
112 | extern bool aml_set_vfm_enable, aml_set_vdec_type_enable; |
113 | |
114 | static void set_default_params(struct aml_vdec_adapt *vdec) |
115 | { |
116 | unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS); |
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 = 1080; |
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 | pr_info("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 | pr_err("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 | pr_err("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 | pr_err("video_component_init %d, failed\n", __LINE__); |
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 | pr_err("video_component_init %d, stbuf_init failed\n", __LINE__); |
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 | pr_err("video_component_init %d, vdec_init failed\n", __LINE__); |
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 | pr_err("video_component_init %d, vdec_init failed\n", |
388 | __LINE__); |
389 | video_component_release(port, pbuf, 2); |
390 | return ret; |
391 | } |
392 | } |
393 | |
394 | if (port->type & PORT_TYPE_ES) { |
395 | ret = esparser_init(pbuf, vdec); |
396 | if (ret < 0) { |
397 | video_component_release(port, pbuf, 3); |
398 | pr_err("esparser_init() failed\n"); |
399 | return ret; |
400 | } |
401 | } |
402 | |
403 | pbuf->flag |= BUF_FLAG_IN_USE; |
404 | |
405 | vdec_connect(vdec); |
406 | |
407 | return 0; |
408 | } |
409 | |
410 | static int vdec_ports_release(struct stream_port_s *port) |
411 | { |
412 | struct aml_vdec_adapt *ada_ctx |
413 | = container_of(port, struct aml_vdec_adapt, port); |
414 | struct vdec_s *vdec = ada_ctx->vdec; |
415 | |
416 | struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; |
417 | struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; |
418 | //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; |
419 | struct vdec_s *slave = NULL; |
420 | |
421 | if (has_hevc_vdec()) { |
422 | if (port->vformat == VFORMAT_HEVC |
423 | || port->vformat == VFORMAT_VP9) |
424 | pvbuf = &bufs[BUF_TYPE_HEVC]; |
425 | } |
426 | |
427 | if (port->type & PORT_TYPE_MPTS) { |
428 | tsync_pcr_stop(); |
429 | tsdemux_release(); |
430 | } |
431 | |
432 | if (port->type & PORT_TYPE_MPPS) |
433 | psparser_release(); |
434 | |
435 | if (port->type & PORT_TYPE_VIDEO) |
436 | video_component_release(port, pvbuf, 0); |
437 | |
438 | if (port->type & PORT_TYPE_AUDIO) |
439 | audio_component_release(port, pabuf, 0); |
440 | |
441 | if (port->type & PORT_TYPE_SUB) |
442 | //sub_port_release(port, psbuf); |
443 | |
444 | if (vdec) { |
445 | if (vdec->slave) |
446 | slave = vdec->slave; |
447 | |
448 | vdec_release(vdec); |
449 | |
450 | if (slave) |
451 | vdec_release(slave); |
452 | vdec = NULL; |
453 | } |
454 | |
455 | port->pcr_inited = 0; |
456 | port->flag = 0; |
457 | |
458 | return 0; |
459 | } |
460 | |
461 | static void set_vdec_properity(struct vdec_s *vdec, |
462 | struct aml_vdec_adapt *ada_ctx) |
463 | { |
464 | vdec->sys_info = &ada_ctx->dec_prop; |
465 | vdec->port = &ada_ctx->port; |
466 | vdec->format = ada_ctx->dec_prop.format; |
467 | vdec->sys_info_store = ada_ctx->dec_prop; |
468 | vdec->vf_receiver_name = ada_ctx->recv_name; |
469 | |
470 | /* binding v4l2 ctx to vdec. */ |
471 | vdec->private = ada_ctx->ctx; |
472 | |
473 | /* set video format, sys info and vfm map.*/ |
474 | vdec->port->vformat = vdec->format; |
475 | vdec->port->type |= PORT_TYPE_VIDEO; |
476 | vdec->port_flag |= PORT_FLAG_VFORMAT; |
477 | if (vdec->slave) { |
478 | vdec->slave->format = ada_ctx->dec_prop.format; |
479 | vdec->slave->port_flag |= PORT_FLAG_VFORMAT; |
480 | } |
481 | |
482 | if (vdec->port->type & PORT_FLAG_DRM) { |
483 | vdec->type = VDEC_TYPE_STREAM_PARSER; |
484 | vdec->port->type |= PORT_TYPE_ES; |
485 | vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO; |
486 | } else { |
487 | vdec->type = VDEC_TYPE_FRAME_BLOCK; |
488 | vdec->port->type |= PORT_TYPE_FRAME; |
489 | vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_OSD; |
490 | } |
491 | |
492 | if (aml_set_vdec_type_enable) { |
493 | if (aml_set_vdec_type == VDEC_TYPE_STREAM_PARSER) { |
494 | vdec->type = VDEC_TYPE_STREAM_PARSER; |
495 | vdec->port->type &= ~PORT_TYPE_FRAME; |
496 | vdec->port->type |= PORT_TYPE_ES; |
497 | ada_ctx->ctx->is_stream_mode = true; |
498 | } else if (aml_set_vdec_type == VDEC_TYPE_FRAME_BLOCK) { |
499 | vdec->type = VDEC_TYPE_FRAME_BLOCK; |
500 | vdec->port->type &= ~PORT_TYPE_ES; |
501 | vdec->port->type |= PORT_TYPE_FRAME; |
502 | ada_ctx->ctx->is_stream_mode = false; |
503 | } |
504 | } |
505 | |
506 | if (aml_set_vfm_enable) |
507 | vdec->frame_base_video_path = aml_set_vfm_path; |
508 | |
509 | vdec->port->flag = vdec->port_flag; |
510 | ada_ctx->vfm_path = vdec->frame_base_video_path; |
511 | ada_ctx->vdec = vdec; |
512 | } |
513 | |
514 | static int vdec_ports_init(struct aml_vdec_adapt *ada_ctx) |
515 | { |
516 | int ret = -1; |
517 | struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO]; |
518 | struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO]; |
519 | //struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE]; |
520 | struct vdec_s *vdec = NULL; |
521 | |
522 | /* create the vdec instance.*/ |
523 | vdec = vdec_create(&ada_ctx->port, NULL); |
524 | if (IS_ERR_OR_NULL(vdec)) |
525 | return -1; |
526 | |
527 | set_vdec_properity(vdec, ada_ctx); |
528 | |
529 | /* init hw and gate*/ |
530 | ret = enable_hardware(vdec->port); |
531 | if (ret < 0) { |
532 | pr_info("enable hw fail.\n"); |
533 | goto error1; |
534 | } |
535 | |
536 | stbuf_fetch_init(); |
537 | user_buffer_init(); |
538 | |
539 | if ((vdec->port->type & PORT_TYPE_AUDIO) |
540 | && (vdec->port_flag & PORT_FLAG_AFORMAT)) { |
541 | ret = audio_component_init(vdec->port, pabuf); |
542 | if (ret < 0) { |
543 | pr_err("audio_component_init failed\n"); |
544 | goto error1; |
545 | } |
546 | } |
547 | |
548 | if ((vdec->port->type & PORT_TYPE_VIDEO) |
549 | && (vdec->port_flag & PORT_FLAG_VFORMAT)) { |
550 | pvbuf->for_4k = 0; |
551 | if (has_hevc_vdec()) { |
552 | if (vdec->port->vformat == VFORMAT_HEVC |
553 | || vdec->port->vformat == VFORMAT_VP9) |
554 | pvbuf = &bufs[BUF_TYPE_HEVC]; |
555 | } |
556 | |
557 | ret = video_component_init(vdec->port, pvbuf); |
558 | if (ret < 0) { |
559 | pr_err("video_component_init failed\n"); |
560 | goto error2; |
561 | } |
562 | |
563 | /* connect vdec at the end after all HW initialization */ |
564 | vdec_connect(vdec); |
565 | } |
566 | |
567 | return 0; |
568 | |
569 | //error3: |
570 | //video_component_release(port, pvbuf, 0); |
571 | error2: |
572 | audio_component_release(vdec->port, pabuf, 0); |
573 | error1: |
574 | return ret; |
575 | } |
576 | |
577 | int video_decoder_init(struct aml_vdec_adapt *vdec) |
578 | { |
579 | int ret = -1; |
580 | |
581 | /* sets configure data */ |
582 | set_default_params(vdec); |
583 | |
584 | /* init the buffer work space and connect vdec.*/ |
585 | ret = vdec_ports_init(vdec); |
586 | if (ret < 0) { |
587 | pr_info("vdec ports init fail.\n"); |
588 | goto out; |
589 | } |
590 | out: |
591 | return ret; |
592 | } |
593 | |
594 | int video_decoder_release(struct aml_vdec_adapt *vdec) |
595 | { |
596 | int ret = -1; |
597 | struct stream_port_s *port = &vdec->port; |
598 | |
599 | ret = vdec_ports_release(port); |
600 | if (ret < 0) { |
601 | pr_info("vdec ports release fail.\n"); |
602 | goto out; |
603 | } |
604 | |
605 | /* disable gates */ |
606 | ret = disable_hardware(port); |
607 | if (ret < 0) { |
608 | pr_info("disable hw fail.\n"); |
609 | goto out; |
610 | } |
611 | out: |
612 | return ret; |
613 | } |
614 | |
615 | int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx, |
616 | const char *buf, unsigned int count) |
617 | { |
618 | int ret = -1; |
619 | int try_cnt = 100; |
620 | struct stream_port_s *port = &ada_ctx->port; |
621 | struct vdec_s *vdec = ada_ctx->vdec; |
622 | struct stream_buf_s *pbuf = NULL; |
623 | |
624 | if (has_hevc_vdec()) { |
625 | pbuf = (port->type & PORT_TYPE_HEVC) ? &bufs[BUF_TYPE_HEVC] : |
626 | &bufs[BUF_TYPE_VIDEO]; |
627 | } else |
628 | pbuf = &bufs[BUF_TYPE_VIDEO]; |
629 | |
630 | /*if (!(port_get_inited(priv))) { |
631 | r = video_decoder_init(priv); |
632 | if (r < 0) |
633 | return r; |
634 | }*/ |
635 | |
636 | do { |
637 | if (vdec->port_flag & PORT_FLAG_DRM) |
638 | ret = drm_write(ada_ctx->filp, pbuf, buf, count); |
639 | else |
640 | ret = esparser_write(ada_ctx->filp, pbuf, buf, count); |
641 | |
642 | if (ret == -EAGAIN) |
643 | msleep(30); |
644 | } while (ret == -EAGAIN && try_cnt--); |
645 | |
646 | if (slow_input) { |
647 | pr_info("slow_input: es codec write size %x\n", ret); |
648 | msleep(10); |
649 | } |
650 | |
651 | #ifdef DATA_DEBUG |
652 | /* dump to file */ |
653 | //dump_write(vbuf, size); |
654 | //pr_info("vbuf: %p, size: %u, ret: %d\n", vbuf, size, ret); |
655 | #endif |
656 | |
657 | return ret; |
658 | } |
659 | |
660 | int is_need_to_buf(struct aml_vdec_adapt *ada_ctx) |
661 | { |
662 | struct vdec_s *vdec = ada_ctx->vdec; |
663 | |
664 | if (vdec->input.have_frame_num > 8) |
665 | return 0; |
666 | else |
667 | return 1; |
668 | } |
669 | |
670 | int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx, |
671 | const char *buf, unsigned int count, unsigned long int timestamp) |
672 | { |
673 | int ret = -1; |
674 | int try_cnt = 100; |
675 | struct vdec_s *vdec = ada_ctx->vdec; |
676 | |
677 | /* set timestamp */ |
678 | vdec_set_timestamp(vdec, timestamp); |
679 | |
680 | do { |
681 | ret = vdec_write_vframe(vdec, buf, count); |
682 | if (ret == -EAGAIN) { |
683 | /*vdec_input_level(&vdec->input);*/ |
684 | msleep(30); |
685 | } |
686 | } while (ret == -EAGAIN && try_cnt--); |
687 | |
688 | if (slow_input) { |
689 | pr_info("slow_input: frame codec write size %d\n", ret); |
690 | msleep(30); |
691 | } |
692 | |
693 | #ifdef DATA_DEBUG |
694 | /* dump to file */ |
695 | dump_write(buf, count); |
696 | #endif |
697 | aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x", |
698 | ada_ctx->ctx->id, buf, count, ret, crc32_le(0, buf, count)); |
699 | |
700 | return ret; |
701 | } |
702 | |
703 | void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx) |
704 | { |
705 | struct vdec_s *vdec = ada_ctx->vdec; |
706 | |
707 | if (vdec) |
708 | vdec_set_eos(vdec, true); |
709 | } |
710 | |
711 | int aml_codec_reset(struct aml_vdec_adapt *ada_ctx) |
712 | { |
713 | struct vdec_s *vdec = ada_ctx->vdec; |
714 | int ret = 0; |
715 | |
716 | if (vdec) { |
717 | vdec_set_eos(vdec, false); |
718 | ret = vdec_reset(vdec); |
719 | } |
720 | |
721 | return ret; |
722 | } |
723 | |
724 | bool is_input_ready(struct aml_vdec_adapt *ada_ctx) |
725 | { |
726 | struct vdec_s *vdec = ada_ctx->vdec; |
727 | int state = VDEC_STATUS_UNINITIALIZED; |
728 | |
729 | if (vdec) { |
730 | state = vdec_get_status(vdec); |
731 | |
732 | if (state == VDEC_STATUS_CONNECTED |
733 | || state == VDEC_STATUS_ACTIVE) |
734 | return true; |
735 | } |
736 | |
737 | return false; |
738 | } |
739 | |
740 | int vdec_frame_number(struct aml_vdec_adapt *ada_ctx) |
741 | { |
742 | struct vdec_s *vdec = ada_ctx->vdec; |
743 | |
744 | if (vdec) |
745 | return vdec_get_frame_num(vdec); |
746 | else |
747 | return -1; |
748 | } |
749 |