forked from milosladni/jepoc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
veavc.c
145 lines (126 loc) · 3.67 KB
/
veavc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
* Copyright (c) 2014 Manuel Braga <mul.braga@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "vepoc.h"
static veavc_encoder_mode encoder_mode = VEAVC_ENCODER_MODE_H264;
void veavc_select_subengine(void)
{
uint32_t ctrl = L(VE_CTRL);
ctrl = (ctrl & 0xfffffff0) | 0xb;
S(ctrl, VE_CTRL);
}
void veavc_init_vle(uint8_t *J, uint32_t size)
{
uint32_t pJ = ve_virt2phys(J);
uint32_t end = pJ + size - 1;
uint32_t maxbits = (size * 8 + 0xffff) & ~0xffff;
uint32_t max = maxbits > 0x0fff0000 ? 0x0fff0000 : maxbits;
S(pJ , VE_AVC_VLE_ADDR);
S(end , VE_AVC_VLE_END);
S(0 , VE_AVC_VLE_OFFSET);
S(max , VE_AVC_VLE_MAX);
printf("[VEAVC] outbuf of size %d, write only max %d bytes\n", size, max / 8);
}
void veavc_init_ctrl(veavc_encoder_mode mode)
{
uint32_t trigger = (mode & 1) << 16;
uint32_t status;
encoder_mode = mode;
S(0x0000000f , VE_AVC_CTRL);
S(trigger , VE_AVC_TRIGGER);
/* clear status bits */
status = L(VE_AVC_STATUS);
S(status | 0xf, VE_AVC_STATUS);
}
void veavc_jpeg_parameters(uint8_t fill1, uint8_t stuff, uint32_t biasY, uint32_t biasC)
{
uint32_t valfill1 = fill1 > 0 ? 1 : 0;
uint32_t valstuff = stuff > 0 ? 1 : 0;
uint32_t value = 0;
value |= (valfill1 & 1) << 31;
value |= (valstuff & 1) << 30;
value |= (biasC & 0x7ff) << 16;
value |= (biasY & 0x7ff) << 0;
S(value, VE_AVC_PARAM);
}
static const char* status_to_print(uint32_t status)
{
uint32_t value = status & 0xf;
if(value == 0) return "none";
if(value == 1) return "success";
if(value == 2) return "failed";
return "unknown";
}
void veavc_put_bits(uint8_t nbits, uint32_t data)
{
uint32_t trigger = (encoder_mode & 1) << 16;
uint32_t status;
trigger |= (nbits & 0x3f) << 8;
trigger |= 1;
S(data , VE_AVC_BASIC_BITS);
S(trigger, VE_AVC_TRIGGER);
status = L(VE_AVC_STATUS) & 0xf;
if(status)
printf("[VEAVC] put bits status %d (%s)\n", status, status_to_print(status));
}
void veavc_sdram_index(uint32_t index)
{
S(index, VE_AVC_SDRAM_INDEX);
}
void veavc_jpeg_quantization(uint16_t *tableY, uint16_t *tableC, uint32_t length)
{
uint32_t data;
int i;
veavc_sdram_index(0x0);
/*
When compared to libjpeg, there are still rounding errors in the
coefficients values (around 1 unit of difference).
*/
for(i = 0; i < length; i++)
{
data = 0x0000ffff & (0xffff / tableY[i]);
data |= 0x00ff0000 & (((tableY[i] + 1) / 2) << 16);
S(data, VE_AVC_SDRAM_DATA);
}
for(i = 0; i < length; i++)
{
data = 0x0000ffff & (0xffff / tableC[i]);
data |= 0x00ff0000 & (((tableC[i] + 1) / 2) << 16);
S(data, VE_AVC_SDRAM_DATA);
}
}
void veavc_launch_encoding(void)
{
uint32_t trigger = (encoder_mode & 1) << 16;
trigger |= 8;
S(trigger, VE_AVC_TRIGGER);
}
void veavc_check_status(void)
{
uint32_t status = L(VE_AVC_STATUS) & 0xf;
if(status)
printf("[VEAVC] finish status %d (%s)\n", status, status_to_print(status));
}
uint32_t veavc_get_written(void)
{
uint32_t bits = L(VE_AVC_VLE_LENGTH);
return bits / 8;
}