• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "aml_vcodec_vfm.h"
21 #include "aml_vcodec_vfq.h"
22 #include "aml_vcodec_util.h"
23 #include "aml_vcodec_adapt.h"
24 #include <media/v4l2-mem2mem.h>
25 
26 #define KERNEL_ATRACE_TAG KERNEL_ATRACE_TAG_VIDEO_COMPOSER
27 #include <trace/events/meson_atrace.h>
28 
29 #define RECEIVER_NAME	"v4l2-video"
30 #define PROVIDER_NAME	"v4l2-video"
31 
vdec_vf_peek(void * op_arg)32 static struct vframe_s *vdec_vf_peek(void *op_arg)
33 {
34 	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
35 
36 	return vfq_peek(&vfm->vf_que);
37 }
38 
vdec_vf_get(void * op_arg)39 static struct vframe_s *vdec_vf_get(void *op_arg)
40 {
41 	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
42 
43 	return vfq_pop(&vfm->vf_que);
44 }
45 
vdec_vf_put(struct vframe_s * vf,void * op_arg)46 static void vdec_vf_put(struct vframe_s *vf, void *op_arg)
47 {
48 	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
49 
50 	/* If the video frame from amvide that means */
51 	/* the data has been processed and finished, */
52 	/* then push back to VDA. thus we don't put the */
53 	/* buffer to the decoder directly.*/
54 
55 	//vf_put(vf, vfm->recv_name);
56 	//vf_notify_provider(vfm->recv_name, VFRAME_EVENT_RECEIVER_PUT, NULL);
57 
58 	if (vfq_level(&vfm->vf_que_recycle) > POOL_SIZE - 1) {
59 		v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_ERROR, "vfq full.\n");
60 		return;
61 	}
62 
63 	atomic_set(&vf->use_cnt, 1);
64 
65 	vfq_push(&vfm->vf_que_recycle, vf);
66 
67 	/* schedule capture work. */
68 	vdec_device_vf_run(vfm->ctx);
69 }
70 
vdec_event_cb(int type,void * data,void * private_data)71 static int vdec_event_cb(int type, void *data, void *private_data)
72 {
73 
74 	if (type & VFRAME_EVENT_RECEIVER_PUT) {
75 	} else if (type & VFRAME_EVENT_RECEIVER_GET) {
76 	} else if (type & VFRAME_EVENT_RECEIVER_FRAME_WAIT) {
77 	}
78 	return 0;
79 }
80 
vdec_vf_states(struct vframe_states * states,void * op_arg)81 static int vdec_vf_states(struct vframe_states *states, void *op_arg)
82 {
83 	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)op_arg;
84 
85 	states->vf_pool_size	= POOL_SIZE;
86 	states->buf_recycle_num	= 0;
87 	states->buf_free_num	= POOL_SIZE - vfq_level(&vfm->vf_que);
88 	states->buf_avail_num	= vfq_level(&vfm->vf_que);
89 
90 	return 0;
91 }
92 
video_vf_put(char * receiver,struct vdec_v4l2_buffer * fb,int id)93 void video_vf_put(char *receiver, struct vdec_v4l2_buffer *fb, int id)
94 {
95 	struct vframe_provider_s *vfp = vf_get_provider(receiver);
96 	struct vframe_s *vf = (struct vframe_s *)fb->vf_handle;
97 
98 	ATRACE_COUNTER("v4l2_to", vf->index_disp);
99 
100 	v4l_dbg(0, V4L_DEBUG_CODEC_OUTPUT,
101 		"[%d]: TO   (%s) vf: %p, idx: %d, "
102 		"Y:(%lx, %u) C/U:(%lx, %u) V:(%lx, %u)\n",
103 		id, vfp->name, vf, vf->index,
104 		fb->m.mem[0].addr, fb->m.mem[0].size,
105 		fb->m.mem[1].addr, fb->m.mem[1].size,
106 		fb->m.mem[2].addr, fb->m.mem[2].size);
107 
108 	if (vfp && vf && atomic_dec_and_test(&vf->use_cnt))
109 		vf_put(vf, receiver);
110 }
111 
112 static const struct vframe_operations_s vf_provider = {
113 	.peek		= vdec_vf_peek,
114 	.get		= vdec_vf_get,
115 	.put		= vdec_vf_put,
116 	.event_cb	= vdec_event_cb,
117 	.vf_states	= vdec_vf_states,
118 };
119 
video_receiver_event_fun(int type,void * data,void * private_data)120 static int video_receiver_event_fun(int type, void *data, void *private_data)
121 {
122 	int ret = 0;
123 	struct vframe_states states;
124 	struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data;
125 
126 	switch (type) {
127 	case VFRAME_EVENT_PROVIDER_UNREG: {
128 		if (vf_get_receiver(vfm->prov_name)) {
129 			v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
130 				"unreg %s provider.\n",
131 				vfm->prov_name);
132 			vf_unreg_provider(&vfm->vf_prov);
133 		}
134 
135 		break;
136 	}
137 
138 	case VFRAME_EVENT_PROVIDER_START: {
139 		if (vf_get_receiver(vfm->prov_name)) {
140 			v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
141 				"reg %s provider.\n",
142 				vfm->prov_name);
143 			vf_provider_init(&vfm->vf_prov, vfm->prov_name,
144 				&vf_provider, vfm);
145 			vf_reg_provider(&vfm->vf_prov);
146 			vf_notify_receiver(vfm->prov_name,
147 				VFRAME_EVENT_PROVIDER_START, NULL);
148 		}
149 
150 		vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]);
151 		vfq_init(&vfm->vf_que_recycle, POOL_SIZE + 1, &vfm->pool_recycle[0]);
152 
153 		break;
154 	}
155 
156 	case VFRAME_EVENT_PROVIDER_QUREY_STATE: {
157 		vdec_vf_states(&states, vfm);
158 		if (states.buf_avail_num > 0)
159 			ret = RECEIVER_ACTIVE;
160 		break;
161 	}
162 
163 	case VFRAME_EVENT_PROVIDER_VFRAME_READY: {
164 		if (vfq_level(&vfm->vf_que) > POOL_SIZE - 1)
165 			ret = -1;
166 
167 		if (!vf_peek(vfm->recv_name))
168 			ret = -1;
169 
170 		vfm->vf = vf_get(vfm->recv_name);
171 		if (!vfm->vf)
172 			ret = -1;
173 
174 		if (ret < 0) {
175 			v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_ERROR, "receiver vf err.\n");
176 			break;
177 		}
178 
179 		vfq_push(&vfm->vf_que, vfm->vf);
180 
181 		if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO) {
182 			vf_notify_receiver(vfm->prov_name,
183 				VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
184 			break;
185 		}
186 
187 		/* schedule capture work. */
188 		vdec_device_vf_run(vfm->ctx);
189 
190 		break;
191 	}
192 
193 	default:
194 		v4l_dbg(vfm->ctx, V4L_DEBUG_CODEC_EXINFO,
195 			"the vf event is %d", type);
196 	}
197 
198 	return ret;
199 }
200 
201 static const struct vframe_receiver_op_s vf_receiver = {
202 	.event_cb	= video_receiver_event_fun
203 };
204 
peek_video_frame(struct vcodec_vfm_s * vfm)205 struct vframe_s *peek_video_frame(struct vcodec_vfm_s *vfm)
206 {
207 	if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO)
208 		return vfq_peek(&vfm->vf_que_recycle);
209 	else
210 		return vfq_peek(&vfm->vf_que);
211 }
212 
get_video_frame(struct vcodec_vfm_s * vfm)213 struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm)
214 {
215 	if (vfm->ada_ctx->vfm_path == FRAME_BASE_PATH_V4L_VIDEO)
216 		return vfq_pop(&vfm->vf_que_recycle);
217 	else
218 		return vfq_pop(&vfm->vf_que);
219 }
220 
vcodec_vfm_init(struct vcodec_vfm_s * vfm)221 int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
222 {
223 	int ret;
224 
225 	snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d",
226 		RECEIVER_NAME, vfm->ctx->id);
227 	snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d",
228 		PROVIDER_NAME, vfm->ctx->id);
229 
230 	vfm->ada_ctx->recv_name = vfm->recv_name;
231 
232 	vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm);
233 	ret = vf_reg_receiver(&vfm->vf_recv);
234 
235 	vfm->vfm_initialized = ret ? false : true;
236 
237 	return ret;
238 }
239 
vcodec_vfm_release(struct vcodec_vfm_s * vfm)240 void vcodec_vfm_release(struct vcodec_vfm_s *vfm)
241 {
242 	if (vfm->vfm_initialized)
243 		vf_unreg_receiver(&vfm->vf_recv);
244 }
245 
246