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