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