├── h264enc ├── .gitignore ├── Makefile ├── README.md ├── h264enc.h ├── main.c └── h264enc.c ├── jpeg-test ├── .gitignore ├── config.mk ├── README ├── Makefile ├── jpeg.h ├── jpeg.c └── main.c ├── mpeg-test ├── .gitignore ├── config.mk ├── Makefile ├── mpeg.h ├── mpeg.c └── main.c ├── .gitignore ├── README └── common ├── disp.h ├── disp.c ├── ve.h ├── ve.c └── sunxi_disp_ioctl.h /h264enc/.gitignore: -------------------------------------------------------------------------------- 1 | h264enc 2 | -------------------------------------------------------------------------------- /jpeg-test/.gitignore: -------------------------------------------------------------------------------- 1 | jpeg-test 2 | -------------------------------------------------------------------------------- /mpeg-test/.gitignore: -------------------------------------------------------------------------------- 1 | mpeg-test 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *~ 3 | *.o 4 | *.d 5 | 6 | !.gitignore 7 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Random code from my reverse engineering efforts of Allwinners CedarX. 2 | -------------------------------------------------------------------------------- /jpeg-test/config.mk: -------------------------------------------------------------------------------- 1 | TARGET = jpeg-test 2 | SRC = main.c jpeg.c ../common/disp.c ../common/ve.c 3 | CFLAGS = -Wall -Wextra -O3 -I../common 4 | LDFLAGS = -lpthread 5 | -------------------------------------------------------------------------------- /mpeg-test/config.mk: -------------------------------------------------------------------------------- 1 | TARGET = mpeg-test 2 | SRC = main.c mpeg.c ../common/disp.c ../common/ve.c 3 | CFLAGS = -Wall -Wextra -O3 -I../common 4 | CFLAGS += $(shell pkg-config --cflags libavformat libavcodec) 5 | LDFLAGS = -lpthread $(shell pkg-config --libs libavformat libavcodec) 6 | -------------------------------------------------------------------------------- /h264enc/Makefile: -------------------------------------------------------------------------------- 1 | TARGET = h264enc 2 | SRC = main.c h264enc.c ../common/ve.c 3 | CFLAGS = -Wall -O3 -I../common 4 | LDFLAGS = -lpthread 5 | LIBS = 6 | CC = gcc 7 | 8 | MAKEFLAGS += -rR --no-print-directory 9 | 10 | DEP_CFLAGS = -MD -MP -MQ $@ 11 | 12 | OBJ = $(addsuffix .o,$(basename $(SRC))) 13 | DEP = $(addsuffix .d,$(basename $(SRC))) 14 | 15 | .PHONY: clean all 16 | 17 | all: $(TARGET) 18 | $(TARGET): $(OBJ) 19 | $(CC) $(LDFLAGS) $(OBJ) $(LIBS) -o $@ 20 | 21 | clean: 22 | rm -f $(OBJ) 23 | rm -f $(DEP) 24 | rm -f $(TARGET) 25 | 26 | %.o: %.c 27 | $(CC) $(DEP_CFLAGS) $(CFLAGS) -c $< -o $@ 28 | 29 | include $(wildcard $(DEP)) 30 | -------------------------------------------------------------------------------- /jpeg-test/README: -------------------------------------------------------------------------------- 1 | Proof of Concept JPEG decoder using Allwinners CedarX 2 | ===================================================== 3 | 4 | *WARNING*: Don't use on "production systems". This was made by reverse 5 | engineering and might crash your system or destroy data! 6 | It was made only for my personal use of testing the reverse engineered 7 | things, so don't expect good code quality. It's far from complete and 8 | might crash if the JPEG doesn't fit it's requirements! 9 | 10 | Usage: 11 | ------ 12 | 13 | make 14 | ./jpeg-test example.jpg 15 | 16 | If everything works, output is .ppm (Portable Pixmap). 17 | You might pipe it into ImageMagick: 18 | 19 | ./jpeg-test example.jpg | display - 20 | -------------------------------------------------------------------------------- /jpeg-test/Makefile: -------------------------------------------------------------------------------- 1 | include config.mk 2 | 3 | CFLAGS += -MD -MP -MQ $@ 4 | MAKEFLAGS += -rR --no-print-directory 5 | 6 | OBJ = $(addsuffix .o,$(basename $(SRC))) 7 | 8 | ifdef V 9 | ifeq ("$(origin V)", "command line") 10 | VERBOSE = $(V) 11 | endif 12 | endif 13 | ifndef VERBOSE 14 | VERBOSE = 0 15 | endif 16 | 17 | ifeq ($(VERBOSE), 1) 18 | Q = 19 | else 20 | Q = @ 21 | endif 22 | 23 | $(TARGET): $(OBJ) 24 | @echo "LD $(TARGET)" 25 | $(Q)g++ $(LDFLAGS) $(OBJ) -o $@ 26 | 27 | .PHONY: clean 28 | clean: 29 | @echo "RM *.o" 30 | $(Q)rm -f *.o 31 | @echo "RM *.d" 32 | $(Q)rm -f *.d 33 | @echo "RM $(TARGET)" 34 | $(Q)rm -f $(TARGET) 35 | 36 | %.o: %.c config.mk 37 | @echo "CC $<" 38 | $(Q)gcc $(CFLAGS) -c $< -o $@ 39 | 40 | include $(wildcard $(foreach f,$(OBJ),$(basename $(f)).d)) 41 | -------------------------------------------------------------------------------- /mpeg-test/Makefile: -------------------------------------------------------------------------------- 1 | include config.mk 2 | 3 | CFLAGS += -MD -MP -MQ $@ 4 | MAKEFLAGS += -rR --no-print-directory 5 | 6 | OBJ = $(addsuffix .o,$(basename $(SRC))) 7 | 8 | ifdef V 9 | ifeq ("$(origin V)", "command line") 10 | VERBOSE = $(V) 11 | endif 12 | endif 13 | ifndef VERBOSE 14 | VERBOSE = 0 15 | endif 16 | 17 | ifeq ($(VERBOSE), 1) 18 | Q = 19 | else 20 | Q = @ 21 | endif 22 | 23 | $(TARGET): $(OBJ) 24 | @echo "LD $(TARGET)" 25 | $(Q)g++ $(LDFLAGS) $(OBJ) -o $@ 26 | 27 | .PHONY: clean 28 | clean: 29 | @echo "RM *.o" 30 | $(Q)rm -f *.o 31 | @echo "RM *.d" 32 | $(Q)rm -f *.d 33 | @echo "RM $(TARGET)" 34 | $(Q)rm -f $(TARGET) 35 | 36 | %.o: %.c config.mk 37 | @echo "CC $<" 38 | $(Q)gcc $(CFLAGS) -c $< -o $@ 39 | 40 | include $(wildcard $(foreach f,$(OBJ),$(basename $(f)).d)) 41 | -------------------------------------------------------------------------------- /h264enc/README.md: -------------------------------------------------------------------------------- 1 | Proof of Concept hardware accelerated H264 encoder for sunxi 2 | ============================================================ 3 | 4 | This is a basic example for using the H264 hardware encoder for sunxi SoCs. 5 | 6 | *It is just a proof of concept and not recommended for production use!* 7 | 8 | Limitations: 9 | ------------ 10 | 11 | - no B frames 12 | - constant QP 13 | - only raw nv12 or nv16 input and bytestream output 14 | - ... many more 15 | 16 | The old mplayer doesn't seem to like the raw bytestream output, maybe our 17 | bytestream is still a little bit erroneous. 18 | 19 | 20 | Usage: 21 | ------ 22 | 23 | make 24 | 25 | ffmpeg -i -pix_fmt nv12 \ 26 | -vf pad="width=trunc((iw+15)/16)*16:height=trunc((ih+15)/16)*16" \ 27 | -f rawvideo pipe: | ./h264enc - 28 | 29 | It is *important* that the input data is in nv12 format and has a width and 30 | height multiple of 16, this is ensured by the "-vf pad" above. 31 | 32 | For example: 33 | 34 | ffmpeg -i bigbuckbunny.mpg -pix_fmt nv12 \ 35 | -vf pad="width=trunc((iw+15)/16)*16:height=trunc((ih+15)/16)*16" \ 36 | -f rawvideo pipe: | ./h264enc - 854 480 bigbuckbunny.264 37 | 38 | ffplay bigbuckbunny.264 39 | -------------------------------------------------------------------------------- /common/disp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Jens Kuske 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, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | */ 20 | 21 | #ifndef __DISP_H__ 22 | #define __DISP_H__ 23 | 24 | #include 25 | 26 | #define COLOR_YUV420 (0) 27 | #define COLOR_YUV422 (2) 28 | 29 | int disp_open(void); 30 | int disp_set_para(const uint32_t luma_buffer, const uint32_t chroma_buffer, 31 | const int color_format, const int width, const int height, 32 | const int out_x, const int out_y, const int put_width, const int out_height); 33 | int disp_new_frame(const uint32_t luma_buffer, const uint32_t chroma_buffer, 34 | const int id, const int frame_rate); 35 | void disp_close(void); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /jpeg-test/jpeg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple JPEG parser (only basic functions) 3 | * 4 | * Copyright (c) 2013 Jens Kuske 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef __JPEG_H__ 24 | #define __JPEG_H__ 25 | 26 | #include 27 | 28 | struct jpeg_t 29 | { 30 | uint8_t bits; 31 | uint16_t width; 32 | uint16_t height; 33 | struct comp_t 34 | { 35 | uint8_t samp_h; 36 | uint8_t samp_v; 37 | uint8_t qt; 38 | uint8_t ht_ac; 39 | uint8_t ht_dc; 40 | } comp[3]; 41 | struct quant_t 42 | { 43 | uint8_t coeff[64]; 44 | } *quant[4]; 45 | struct huffman_t 46 | { 47 | uint8_t num[16]; 48 | uint8_t codes[256]; 49 | } *huffman[8]; 50 | uint16_t restart_interval; 51 | uint8_t *data; 52 | uint32_t data_len; 53 | }; 54 | 55 | int parse_jpeg(struct jpeg_t *jpeg, const uint8_t *data, const int len); 56 | void dump_jpeg(const struct jpeg_t *jpeg); 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /mpeg-test/mpeg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple MPEG1/2 parser 3 | * 4 | * Copyright (c) 2013 Jens Kuske 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #ifndef __MPEG_H__ 24 | #define __MPEG_H__ 25 | 26 | #include 27 | 28 | struct mpeg_t 29 | { 30 | const uint8_t *data; 31 | int len; 32 | int pos; 33 | unsigned int gop; 34 | enum { MPEG1, MPEG2 } type; 35 | 36 | uint16_t width; 37 | uint16_t height; 38 | 39 | uint16_t temporal_reference; 40 | enum { PCT_I = 1, PCT_P, PCT_B, PCT_D } picture_coding_type; 41 | uint8_t full_pel_forward_vector; 42 | uint8_t full_pel_backward_vector; 43 | uint8_t f_code[2][2]; 44 | 45 | uint8_t intra_dc_precision; 46 | uint8_t picture_structure; 47 | uint8_t top_field_first; 48 | uint8_t frame_pred_frame_dct; 49 | uint8_t concealment_motion_vectors; 50 | uint8_t q_scale_type; 51 | uint8_t intra_vlc_format; 52 | uint8_t alternate_scan; 53 | }; 54 | 55 | int parse_mpeg(struct mpeg_t * const mpeg); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /h264enc/h264enc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Jens Kuske 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, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | */ 20 | 21 | #ifndef __H264ENC_H__ 22 | #define __H264ENC_H__ 23 | 24 | struct h264enc_params { 25 | unsigned int width; 26 | unsigned int height; 27 | 28 | unsigned int src_width; 29 | unsigned int src_height; 30 | enum color_format { H264_FMT_NV12 = 0, H264_FMT_NV16 = 1 } src_format; 31 | 32 | unsigned int profile_idc, level_idc; 33 | 34 | enum { H264_EC_CAVLC = 0, H264_EC_CABAC = 1 } entropy_coding_mode; 35 | 36 | unsigned int qp; 37 | 38 | unsigned int keyframe_interval; 39 | }; 40 | 41 | typedef struct h264enc_internal h264enc; 42 | 43 | h264enc *h264enc_new(const struct h264enc_params *p); 44 | void h264enc_free(h264enc *c); 45 | void *h264enc_get_input_buffer(const h264enc *c); 46 | void *h264enc_get_bytestream_buffer(const h264enc *c); 47 | unsigned int h264enc_get_bytestream_length(const h264enc *c); 48 | int h264enc_encode_picture(h264enc *c); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /h264enc/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014 Jens Kuske 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, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "ve.h" 29 | #include "h264enc.h" 30 | 31 | static int read_frame(int fd, void *buffer, int size) 32 | { 33 | int total = 0, len; 34 | while (total < size) 35 | { 36 | len = read(fd, buffer + total, size - total); 37 | if (len == 0) 38 | return 0; 39 | total += len; 40 | } 41 | return 1; 42 | } 43 | 44 | int main(const int argc, const char **argv) 45 | { 46 | if (argc != 5) 47 | { 48 | printf("Usage: %s \n", argv[0]); 49 | return EXIT_FAILURE; 50 | } 51 | 52 | int width = atoi(argv[2]); 53 | int height = atoi(argv[3]); 54 | 55 | if (!ve_open()) 56 | return EXIT_FAILURE; 57 | 58 | int in = 0, out; 59 | if (strcmp(argv[1], "-") != 0) 60 | { 61 | if ((in = open(argv[1], O_RDONLY)) == -1) 62 | { 63 | printf("could not open input file\n"); 64 | return EXIT_FAILURE; 65 | } 66 | } 67 | 68 | if ((out = open(argv[4], O_CREAT | O_RDWR | O_TRUNC, 69 | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) 70 | { 71 | printf("could not open output file\n"); 72 | return EXIT_FAILURE; 73 | } 74 | 75 | struct h264enc_params params; 76 | params.src_width = (width + 15) & ~15; 77 | params.width = width; 78 | params.src_height = (height + 15) & ~15; 79 | params.height = height; 80 | params.src_format = H264_FMT_NV12; 81 | params.profile_idc = 77; 82 | params.level_idc = 41; 83 | params.entropy_coding_mode = H264_EC_CABAC; 84 | params.qp = 24; 85 | params.keyframe_interval = 25; 86 | 87 | h264enc *encoder = h264enc_new(¶ms); 88 | if (encoder == NULL) 89 | { 90 | printf("could not create encoder\n"); 91 | goto err; 92 | } 93 | 94 | void* output_buf = h264enc_get_bytestream_buffer(encoder); 95 | 96 | int input_size = params.src_width * (params.src_height + params.src_height / 2); 97 | void* input_buf = h264enc_get_input_buffer(encoder); 98 | 99 | while (read_frame(in, input_buf, input_size)) 100 | { 101 | if (h264enc_encode_picture(encoder)) 102 | write(out, output_buf, h264enc_get_bytestream_length(encoder)); 103 | else 104 | printf("encoding error\n"); 105 | } 106 | 107 | h264enc_free(encoder); 108 | 109 | err: 110 | ve_close(); 111 | close(out); 112 | close(in); 113 | 114 | return EXIT_SUCCESS; 115 | } 116 | -------------------------------------------------------------------------------- /common/disp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Jens Kuske 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, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "disp.h" 27 | #include "sunxi_disp_ioctl.h" 28 | 29 | #define DRAM_OFFSET (0x40000000) 30 | 31 | static int fd = -1; 32 | static int layer = -1; 33 | static int last_id = -1; 34 | 35 | int disp_open(void) 36 | { 37 | fd = open("/dev/disp", O_RDWR); 38 | if (fd == -1) 39 | return 0; 40 | 41 | uint32_t args[4]; 42 | 43 | args[0] = 0; 44 | args[1] = DISP_LAYER_WORK_MODE_SCALER; 45 | args[2] = 0; 46 | args[3] = 0; 47 | layer = ioctl(fd, DISP_CMD_LAYER_REQUEST, args); 48 | 49 | if (layer > 0) 50 | return 1; 51 | 52 | close(fd); 53 | return 0; 54 | } 55 | 56 | int disp_set_para(const uint32_t luma_buffer, const uint32_t chroma_buffer, 57 | const int color_format, const int width, const int height, 58 | const int out_x, const int out_y, const int out_width, const int out_height) 59 | { 60 | uint32_t args[4]; 61 | __disp_layer_info_t layer_info; 62 | memset(&layer_info, 0, sizeof(layer_info)); 63 | layer_info.pipe = 1; 64 | layer_info.mode = DISP_LAYER_WORK_MODE_SCALER; 65 | layer_info.fb.mode = DISP_MOD_MB_UV_COMBINED; 66 | switch (color_format) 67 | { 68 | case COLOR_YUV420: 69 | layer_info.fb.format = DISP_FORMAT_YUV420; 70 | break; 71 | case COLOR_YUV422: 72 | layer_info.fb.format = DISP_FORMAT_YUV422; 73 | break; 74 | default: 75 | return 0; 76 | break; 77 | } 78 | layer_info.fb.seq = DISP_SEQ_UVUV; 79 | layer_info.fb.br_swap = 0; 80 | layer_info.fb.addr[0] = luma_buffer + DRAM_OFFSET; 81 | layer_info.fb.addr[1] = chroma_buffer + DRAM_OFFSET; 82 | 83 | layer_info.fb.cs_mode = DISP_BT601; 84 | layer_info.fb.size.width = width; 85 | layer_info.fb.size.height = height; 86 | layer_info.src_win.x = 0; 87 | layer_info.src_win.y = 0; 88 | layer_info.src_win.width = width; 89 | layer_info.src_win.height = height; 90 | layer_info.scn_win.x = out_x; 91 | layer_info.scn_win.y = out_y; 92 | layer_info.scn_win.width = out_width; 93 | layer_info.scn_win.height = out_height; 94 | 95 | args[0] = 0; 96 | args[1] = layer; 97 | args[2] = (unsigned long)(&layer_info); 98 | args[3] = 0; 99 | ioctl(fd, DISP_CMD_LAYER_SET_PARA, args); 100 | ioctl(fd, DISP_CMD_LAYER_TOP, args); 101 | 102 | ioctl(fd, DISP_CMD_VIDEO_START, args); 103 | ioctl(fd, DISP_CMD_LAYER_OPEN, args); 104 | 105 | return 1; 106 | } 107 | 108 | int disp_new_frame(const uint32_t luma_buffer, const uint32_t chroma_buffer, 109 | const int id, const int frame_rate) 110 | { 111 | uint32_t args[4], i = 0; 112 | 113 | __disp_video_fb_t video; 114 | memset(&video, 0, sizeof(__disp_video_fb_t)); 115 | video.id = id; 116 | video.frame_rate = frame_rate; 117 | video.addr[0] = luma_buffer + DRAM_OFFSET; 118 | video.addr[1] = chroma_buffer + DRAM_OFFSET; 119 | 120 | args[0] = 0; 121 | args[1] = layer; 122 | args[2] = (unsigned long)(&video); 123 | args[3] = 0; 124 | int tmp; 125 | while ((tmp = ioctl(fd, DISP_CMD_VIDEO_GET_FRAME_ID, args)) != last_id) 126 | { 127 | usleep(1000); 128 | if (i++ > 10) 129 | return 0; 130 | } 131 | 132 | ioctl(fd, DISP_CMD_VIDEO_SET_FB, args); 133 | last_id = id; 134 | 135 | return 1; 136 | } 137 | 138 | void disp_close(void) 139 | { 140 | uint32_t args[4]; 141 | 142 | args[0] = 0; 143 | args[1] = layer; 144 | args[2] = 0; 145 | args[3] = 0; 146 | ioctl(fd, DISP_CMD_LAYER_CLOSE, args); 147 | ioctl(fd, DISP_CMD_VIDEO_STOP, args); 148 | ioctl(fd, DISP_CMD_LAYER_RELEASE, args); 149 | 150 | close(fd); 151 | } 152 | -------------------------------------------------------------------------------- /common/ve.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Jens Kuske 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | */ 19 | 20 | #ifndef __VE_H__ 21 | #define __VE_H__ 22 | 23 | #include 24 | 25 | int ve_open(void); 26 | void ve_close(void); 27 | int ve_get_version(void); 28 | int ve_wait(int timeout); 29 | void *ve_get(int engine, uint32_t flags); 30 | void ve_put(void); 31 | 32 | void *ve_malloc(int size); 33 | void ve_free(void *ptr); 34 | uint32_t ve_virt2phys(void *ptr); 35 | void ve_flush_cache(void *start, int len); 36 | 37 | static inline void writeb(uint8_t val, void *addr) 38 | { 39 | *((volatile uint8_t *)addr) = val; 40 | } 41 | 42 | static inline void writel(uint32_t val, void *addr) 43 | { 44 | *((volatile uint32_t *)addr) = val; 45 | } 46 | 47 | static inline uint32_t readl(void *addr) 48 | { 49 | return *((volatile uint32_t *) addr); 50 | } 51 | 52 | #define VE_ENGINE_MPEG 0x0 53 | #define VE_ENGINE_H264 0x1 54 | #define VE_ENGINE_AVC 0xb 55 | 56 | #define VE_CTRL 0x000 57 | #define VE_VERSION 0x0f0 58 | 59 | #define VE_MPEG_PIC_HDR 0x100 60 | #define VE_MPEG_VOP_HDR 0x104 61 | #define VE_MPEG_SIZE 0x108 62 | #define VE_MPEG_FRAME_SIZE 0x10c 63 | #define VE_MPEG_MBA 0x110 64 | #define VE_MPEG_CTRL 0x114 65 | #define VE_MPEG_TRIGGER 0x118 66 | #define VE_MPEG_STATUS 0x11c 67 | #define VE_MPEG_TRBTRD_FIELD 0x120 68 | #define VE_MPEG_TRBTRD_FRAME 0x124 69 | #define VE_MPEG_VLD_ADDR 0x128 70 | #define VE_MPEG_VLD_OFFSET 0x12c 71 | #define VE_MPEG_VLD_LEN 0x130 72 | #define VE_MPEG_VLD_END 0x134 73 | #define VE_MPEG_MBH_ADDR 0x138 74 | #define VE_MPEG_DCAC_ADDR 0x13c 75 | #define VE_MPEG_NCF_ADDR 0x144 76 | #define VE_MPEG_REC_LUMA 0x148 77 | #define VE_MPEG_REC_CHROMA 0x14c 78 | #define VE_MPEG_FWD_LUMA 0x150 79 | #define VE_MPEG_FWD_CHROMA 0x154 80 | #define VE_MPEG_BACK_LUMA 0x158 81 | #define VE_MPEG_BACK_CHROMA 0x15c 82 | #define VE_MPEG_IQ_MIN_INPUT 0x180 83 | #define VE_MPEG_QP_INPUT 0x184 84 | #define VE_MPEG_JPEG_SIZE 0x1b8 85 | #define VE_MPEG_JPEG_RES_INT 0x1c0 86 | #define VE_MPEG_ROT_LUMA 0x1cc 87 | #define VE_MPEG_ROT_CHROMA 0x1d0 88 | #define VE_MPEG_SDROT_CTRL 0x1d4 89 | #define VE_MPEG_RAM_WRITE_PTR 0x1e0 90 | #define VE_MPEG_RAM_WRITE_DATA 0x1e4 91 | 92 | #define VE_H264_FRAME_SIZE 0x200 93 | #define VE_H264_PIC_HDR 0x204 94 | #define VE_H264_SLICE_HDR 0x208 95 | #define VE_H264_SLICE_HDR2 0x20c 96 | #define VE_H264_PRED_WEIGHT 0x210 97 | #define VE_H264_QP_PARAM 0x21c 98 | #define VE_H264_CTRL 0x220 99 | #define VE_H264_TRIGGER 0x224 100 | #define VE_H264_STATUS 0x228 101 | #define VE_H264_CUR_MB_NUM 0x22c 102 | #define VE_H264_VLD_ADDR 0x230 103 | #define VE_H264_VLD_OFFSET 0x234 104 | #define VE_H264_VLD_LEN 0x238 105 | #define VE_H264_VLD_END 0x23c 106 | #define VE_H264_SDROT_CTRL 0x240 107 | #define VE_H264_OUTPUT_FRAME_IDX 0x24c 108 | #define VE_H264_EXTRA_BUFFER1 0x250 109 | #define VE_H264_EXTRA_BUFFER2 0x254 110 | #define VE_H264_BASIC_BITS 0x2dc 111 | #define VE_H264_RAM_WRITE_PTR 0x2e0 112 | #define VE_H264_RAM_WRITE_DATA 0x2e4 113 | 114 | #define VE_SRAM_H264_PRED_WEIGHT_TABLE 0x000 115 | #define VE_SRAM_H264_FRAMEBUFFER_LIST 0x400 116 | #define VE_SRAM_H264_REF_LIST0 0x640 117 | #define VE_SRAM_H264_REF_LIST1 0x664 118 | #define VE_SRAM_H264_SCALING_LISTS 0x800 119 | 120 | #define VE_ISP_INPUT_SIZE 0xa00 121 | #define VE_ISP_INPUT_STRIDE 0xa04 122 | #define VE_ISP_CTRL 0xa08 123 | #define VE_ISP_INPUT_LUMA 0xa78 124 | #define VE_ISP_INPUT_CHROMA 0xa7c 125 | 126 | #define VE_AVC_PARAM 0xb04 127 | #define VE_AVC_QP 0xb08 128 | #define VE_AVC_MOTION_EST 0xb10 129 | #define VE_AVC_CTRL 0xb14 130 | #define VE_AVC_TRIGGER 0xb18 131 | #define VE_AVC_STATUS 0xb1c 132 | #define VE_AVC_BASIC_BITS 0xb20 133 | #define VE_AVC_UNK_BUF 0xb60 134 | #define VE_AVC_VLE_ADDR 0xb80 135 | #define VE_AVC_VLE_END 0xb84 136 | #define VE_AVC_VLE_OFFSET 0xb88 137 | #define VE_AVC_VLE_MAX 0xb8c 138 | #define VE_AVC_VLE_LENGTH 0xb90 139 | #define VE_AVC_REF_LUMA 0xba0 140 | #define VE_AVC_REF_CHROMA 0xba4 141 | #define VE_AVC_REC_LUMA 0xbb0 142 | #define VE_AVC_REC_CHROMA 0xbb4 143 | #define VE_AVC_REF_SLUMA 0xbb8 144 | #define VE_AVC_REC_SLUMA 0xbbc 145 | #define VE_AVC_MB_INFO 0xbc0 146 | 147 | #endif 148 | -------------------------------------------------------------------------------- /mpeg-test/mpeg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple MPEG1/2 parser 3 | * 4 | * Copyright (c) 2013 Jens Kuske 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #include 24 | #include 25 | #include "mpeg.h" 26 | 27 | static int parse_sequence_header(struct mpeg_t * const mpeg) 28 | { 29 | const uint8_t * const data = mpeg->data + mpeg->pos; 30 | 31 | if ((mpeg->pos += 8) > mpeg->len) 32 | return 0; 33 | 34 | mpeg->width = (data[0] << 4) | (data[1] >> 4); 35 | mpeg->height = ((data[1] & 0x0f) << 8) | data[2]; 36 | //ignore 37 | 38 | return 1; 39 | } 40 | 41 | static int parse_extension(struct mpeg_t * const mpeg) 42 | { 43 | const uint8_t * const data = mpeg->data + mpeg->pos; 44 | 45 | if (mpeg->pos > mpeg->len) 46 | return 0; 47 | 48 | switch (data[0] >> 4) 49 | { 50 | case 0x1: 51 | if ((mpeg->pos += 6)> mpeg->len) 52 | return 0; 53 | 54 | //ignore 55 | mpeg->width |= ((data[1] & 0x01) << 13) | ((data[2] & 0x80) << 5); 56 | mpeg->height |= ((data[2] & 0x60) << 7); 57 | //ignore 58 | 59 | return 1; 60 | case 0x2: 61 | //ignore seq_display_ext; 62 | return 1; 63 | case 0x8: 64 | if ((mpeg->pos += 5)> mpeg->len) 65 | return 0; 66 | 67 | mpeg->f_code[0][0] = (data[0] & 0x0f); 68 | mpeg->f_code[0][1] = ((data[1] & 0xf0) >> 4); 69 | mpeg->f_code[1][0] = (data[1] & 0x0f); 70 | mpeg->f_code[1][1] = ((data[2] & 0xf0) >> 4); 71 | mpeg->intra_dc_precision = ((data[2] & 0x0c) >> 2); 72 | mpeg->picture_structure = (data[2] & 0x03); 73 | mpeg->top_field_first = ((data[3] & 0x80) >> 7); 74 | mpeg->frame_pred_frame_dct = ((data[3] & 0x40) >> 6); 75 | mpeg->concealment_motion_vectors = ((data[3] & 0x20) >> 5); 76 | mpeg->q_scale_type = ((data[3] & 0x10) >> 4); 77 | mpeg->intra_vlc_format = ((data[3] & 0x08) >> 3); 78 | mpeg->alternate_scan = ((data[3] & 0x04) >> 2); 79 | //ignore rest 80 | return 1; 81 | default: 82 | fprintf(stderr, "unhandled extension: %01x\n", data[0] >> 4); 83 | break; 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | static int parse_gop(struct mpeg_t * const mpeg) 90 | { 91 | //const uint8_t * const data = mpeg->data + mpeg->pos; 92 | 93 | if ((mpeg->pos += 4) > mpeg->len) 94 | return 0; 95 | 96 | mpeg->gop++; 97 | // ignore data 98 | return 1; 99 | } 100 | 101 | static int parse_picture(struct mpeg_t * const mpeg) 102 | { 103 | const uint8_t * const data = mpeg->data + mpeg->pos; 104 | 105 | if ((mpeg->pos += 4) > mpeg->len) 106 | return 0; 107 | 108 | mpeg->temporal_reference = (data[0] << 2) | (data[1] >> 6); 109 | mpeg->picture_coding_type = ((data[1] & 0x38) >> 3); 110 | if (mpeg->picture_coding_type == 2 || mpeg->picture_coding_type == 3) 111 | { 112 | if (mpeg->pos++ > mpeg->len) 113 | return 0; 114 | 115 | mpeg->full_pel_forward_vector = ((data[3] & 0x04) >> 2); 116 | mpeg->f_code[0][0] = mpeg->f_code[0][1] = ((data[3] & 0x03) << 1) | ((data[4] & 0x80) >> 7); 117 | 118 | if (mpeg->picture_coding_type == 3) 119 | { 120 | mpeg->full_pel_backward_vector = ((data[4] & 0x40) >> 6); 121 | mpeg->f_code[1][0] = mpeg->f_code[1][1] = ((data[4] & 0x38) >> 3); 122 | } 123 | } 124 | else 125 | { 126 | mpeg->full_pel_forward_vector = mpeg->full_pel_backward_vector = 0; 127 | mpeg->f_code[0][0] = mpeg->f_code[0][1] = 0; 128 | mpeg->f_code[1][0] = mpeg->f_code[1][1] = 0; 129 | } 130 | 131 | // ignore extra data 132 | 133 | mpeg->picture_structure = 0x3; 134 | mpeg->top_field_first = 0x1; 135 | mpeg->frame_pred_frame_dct = 0x1; 136 | 137 | return 1; 138 | } 139 | 140 | int parse_mpeg(struct mpeg_t * const mpeg) 141 | { 142 | while (mpeg->pos < mpeg->len) 143 | { 144 | int zeros = 0; 145 | for ( ; mpeg->pos < mpeg->len; mpeg->pos++) 146 | { 147 | if (mpeg->data[mpeg->pos] == 0x00) 148 | zeros++; 149 | else if (mpeg->data[mpeg->pos] == 0x01 && zeros >= 2) 150 | { 151 | mpeg->pos++; 152 | break; 153 | } 154 | else 155 | zeros = 0; 156 | } 157 | 158 | uint8_t marker = mpeg->data[mpeg->pos++]; 159 | 160 | switch (marker) 161 | { 162 | case 0x00: 163 | if (!parse_picture(mpeg)) 164 | return 0; 165 | break; 166 | case 0xb3: 167 | if (!parse_sequence_header(mpeg)) 168 | return 0; 169 | break; 170 | case 0xb5: 171 | if (!parse_extension(mpeg)) 172 | return 0; 173 | break; 174 | case 0xb8: 175 | if (!parse_gop(mpeg)) 176 | return 0; 177 | break; 178 | default: 179 | if (marker >= 0x01 && marker <= 0xaf) 180 | return 1; 181 | 182 | fprintf(stderr, "unhandled startcode: %02x\n", marker); 183 | break; 184 | } 185 | } 186 | return 0; 187 | } 188 | -------------------------------------------------------------------------------- /jpeg-test/jpeg.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple JPEG parser (only basic functions) 3 | * 4 | * Copyright (c) 2013 Jens Kuske 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 19 | * MA 02110-1301, USA. 20 | * 21 | */ 22 | 23 | #include 24 | #include "jpeg.h" 25 | 26 | #define M_SOF0 0xc0 27 | #define M_SOF1 0xc1 28 | #define M_SOF2 0xc2 29 | #define M_SOF3 0xc3 30 | #define M_SOF5 0xc5 31 | #define M_SOF6 0xc6 32 | #define M_SOF7 0xc7 33 | #define M_SOF9 0xc9 34 | #define M_SOF10 0xca 35 | #define M_SOF11 0xcb 36 | #define M_SOF13 0xcd 37 | #define M_SOF14 0xce 38 | #define M_SOF15 0xcf 39 | #define M_SOI 0xd8 40 | #define M_EOI 0xd9 41 | #define M_SOS 0xda 42 | #define M_DQT 0xdb 43 | #define M_DRI 0xdd 44 | #define M_DHT 0xc4 45 | #define M_DAC 0xcc 46 | 47 | const char comp_types[5][3] = { "Y", "Cb", "Cr" }; 48 | 49 | static int process_dqt(struct jpeg_t *jpeg, const uint8_t *data, const int len) 50 | { 51 | int pos; 52 | 53 | for (pos = 0; pos < len; pos += 65) 54 | { 55 | if ((data[pos] >> 4) != 0) 56 | { 57 | fprintf(stderr, "Only 8bit Quantization Tables supported\n"); 58 | return 0; 59 | } 60 | jpeg->quant[data[pos] & 0x03] = (struct quant_t *)&(data[pos + 1]); 61 | } 62 | 63 | return 1; 64 | } 65 | 66 | static int process_dht(struct jpeg_t *jpeg, const uint8_t *data, const int len) 67 | { 68 | int pos = 0; 69 | 70 | while (pos < len) 71 | { 72 | uint8_t id = ((data[pos] & 0x03) << 1) | ((data[pos] & 0x10) >> 4); 73 | 74 | jpeg->huffman[id] = (struct huffman_t *)&(data[pos + 1]); 75 | 76 | int i; 77 | pos += 17; 78 | for (i = 0; i < 16; i++) 79 | pos += jpeg->huffman[id]->num[i]; 80 | } 81 | return 1; 82 | } 83 | 84 | int parse_jpeg(struct jpeg_t *jpeg, const uint8_t *data, const int len) 85 | { 86 | if (len < 2 || data[0] != 0xff || data[1] != M_SOI) 87 | return 0; 88 | 89 | int pos = 2; 90 | int sos = 0; 91 | while (!sos) 92 | { 93 | int i; 94 | 95 | while (pos < len && data[pos] == 0xff) 96 | pos++; 97 | 98 | if (!(pos + 2 < len)) 99 | return 0; 100 | 101 | uint8_t marker = data[pos++]; 102 | uint16_t seg_len = ((uint16_t)data[pos]) << 8 | (uint16_t)data[pos + 1]; 103 | 104 | if (!(pos + seg_len < len)) 105 | return 0; 106 | 107 | switch (marker) 108 | { 109 | case M_DQT: 110 | if (!process_dqt(jpeg, &data[pos + 2], seg_len - 2)) 111 | return 0; 112 | 113 | break; 114 | 115 | case M_DHT: 116 | if (!process_dht(jpeg, &data[pos + 2], seg_len - 2)) 117 | return 0; 118 | 119 | break; 120 | 121 | case M_SOF0: 122 | jpeg->bits = data[pos + 2]; 123 | jpeg->width = ((uint16_t)data[pos + 5]) << 8 | (uint16_t)data[pos + 6]; 124 | jpeg->height = ((uint16_t)data[pos + 3]) << 8 | (uint16_t)data[pos + 4]; 125 | for (i = 0; i < data[pos + 7]; i++) 126 | { 127 | uint8_t id = data[pos + 8 + 3 * i] - 1; 128 | if (id > 2) 129 | { 130 | fprintf(stderr, "only YCbCr supported\n"); 131 | return 0; 132 | } 133 | jpeg->comp[id].samp_h = data[pos + 9 + 3 * i] >> 4; 134 | jpeg->comp[id].samp_v = data[pos + 9 + 3 * i] & 0x0f; 135 | jpeg->comp[id].qt = data[pos + 10 + 3 * i]; 136 | } 137 | break; 138 | 139 | case M_DRI: 140 | jpeg->restart_interval = ((uint16_t)data[pos + 2]) << 8 | (uint16_t)data[pos + 3]; 141 | break; 142 | 143 | case M_SOS: 144 | for (i = 0; i < data[pos + 2]; i++) 145 | { 146 | uint8_t id = data[pos + 3 + 2 * i] - 1; 147 | if (id > 2) 148 | { 149 | fprintf(stderr, "only YCbCr supported\n"); 150 | return 0; 151 | } 152 | jpeg->comp[id].ht_dc = data[pos + 4 + 2 * i] >> 4; 153 | jpeg->comp[id].ht_ac = data[pos + 4 + 2 * i] & 0x0f; 154 | } 155 | sos = 1; 156 | break; 157 | 158 | case M_DAC: 159 | fprintf(stderr, "Arithmetic Coding unsupported\n"); 160 | return 0; 161 | 162 | case M_SOF1: 163 | case M_SOF2: 164 | case M_SOF3: 165 | case M_SOF5: 166 | case M_SOF6: 167 | case M_SOF7: 168 | case M_SOF9: 169 | case M_SOF10: 170 | case M_SOF11: 171 | case M_SOF13: 172 | case M_SOF14: 173 | case M_SOF15: 174 | fprintf(stderr, "only Baseline DCT supported (yet?)\n"); 175 | return 0; 176 | 177 | case M_SOI: 178 | case M_EOI: 179 | fprintf(stderr, "corrupted file\n"); 180 | return 0; 181 | 182 | default: 183 | //fprintf(stderr, "unknown marker: 0x%02x len: %u\n", marker, seg_len); 184 | break; 185 | } 186 | pos += seg_len; 187 | } 188 | 189 | jpeg->data = (uint8_t *)&(data[pos]); 190 | jpeg->data_len = len - pos; 191 | 192 | return 1; 193 | } 194 | 195 | void dump_jpeg(const struct jpeg_t *jpeg) 196 | { 197 | int i, j, k; 198 | printf("Width: %u Height: %u Bits: %u\nRestart interval: %u\nComponents:\n", jpeg->width, jpeg->height, jpeg->bits, jpeg->restart_interval); 199 | for (i = 0; i < 3; i++) 200 | { 201 | if (jpeg->comp[i].samp_h && jpeg->comp[i].samp_v) 202 | printf("\tType: %s Sampling: %u:%u QT: %u HT: %u/%u\n", comp_types[i], jpeg->comp[i].samp_h, jpeg->comp[i].samp_v, jpeg->comp[i].qt, jpeg->comp[i].ht_dc, jpeg->comp[i].ht_dc); 203 | } 204 | printf("Quantization Tables:\n"); 205 | for (i = 0; i < 4; i++) 206 | { 207 | if (jpeg->quant[i]) 208 | { 209 | printf("\tID: %u\n", i); 210 | for (j = 0; j < 64 / 8; j++) 211 | { 212 | printf("\t\t"); 213 | for (k = 0; k < 8; k++) 214 | { 215 | printf("0x%02x ", jpeg->quant[i]->coeff[j * 8 + k]); 216 | } 217 | printf("\n"); 218 | } 219 | } 220 | } 221 | printf("Huffman Tables:\n"); 222 | for (i = 0; i < 8; i++) 223 | { 224 | if (jpeg->huffman[i]) 225 | { 226 | printf("\tID: %u (%cC)\n", (i & 0x06) >> 1, i & 0x01 ? 'A' : 'D'); 227 | int sum = 0; 228 | for (j = 0; j < 16; j++) 229 | { 230 | if (jpeg->huffman[i]->num[j]) 231 | { 232 | printf("\t\t%u bits:", j + 1); 233 | for (k = 0; k < jpeg->huffman[i]->num[j]; k++) 234 | { 235 | printf(" 0x%02x", jpeg->huffman[i]->codes[sum + k]); 236 | } 237 | printf("\n"); 238 | sum += jpeg->huffman[i]->num[j]; 239 | } 240 | } 241 | } 242 | } 243 | printf("Data length: %u\n", jpeg->data_len); 244 | } 245 | -------------------------------------------------------------------------------- /common/ve.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2014 Jens Kuske 3 | * 4 | * This library is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU Lesser General Public 6 | * License as published by the Free Software Foundation; either 7 | * version 2.1 of the License, or (at your option) any later version. 8 | * 9 | * This library is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 | * Lesser General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU Lesser General Public 15 | * License along with this library; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17 | * 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "ve.h" 29 | 30 | #define DEVICE "/dev/cedar_dev" 31 | #define PAGE_OFFSET (0xc0000000) // from kernel 32 | #define PAGE_SIZE (4096) 33 | 34 | enum IOCTL_CMD 35 | { 36 | IOCTL_UNKOWN = 0x100, 37 | IOCTL_GET_ENV_INFO, 38 | IOCTL_WAIT_VE, 39 | IOCTL_RESET_VE, 40 | IOCTL_ENABLE_VE, 41 | IOCTL_DISABLE_VE, 42 | IOCTL_SET_VE_FREQ, 43 | 44 | IOCTL_CONFIG_AVS2 = 0x200, 45 | IOCTL_GETVALUE_AVS2 , 46 | IOCTL_PAUSE_AVS2 , 47 | IOCTL_START_AVS2 , 48 | IOCTL_RESET_AVS2 , 49 | IOCTL_ADJUST_AVS2, 50 | IOCTL_ENGINE_REQ, 51 | IOCTL_ENGINE_REL, 52 | IOCTL_ENGINE_CHECK_DELAY, 53 | IOCTL_GET_IC_VER, 54 | IOCTL_ADJUST_AVS2_ABS, 55 | IOCTL_FLUSH_CACHE 56 | }; 57 | 58 | struct ve_info 59 | { 60 | uint32_t reserved_mem; 61 | int reserved_mem_size; 62 | uint32_t registers; 63 | }; 64 | 65 | struct cedarv_cache_range 66 | { 67 | long start; 68 | long end; 69 | }; 70 | 71 | struct memchunk_t 72 | { 73 | uint32_t phys_addr; 74 | int size; 75 | void *virt_addr; 76 | struct memchunk_t *next; 77 | }; 78 | 79 | static struct 80 | { 81 | int fd; 82 | void *regs; 83 | int version; 84 | struct memchunk_t first_memchunk; 85 | pthread_rwlock_t memory_lock; 86 | pthread_mutex_t device_lock; 87 | } ve = { .fd = -1, .memory_lock = PTHREAD_RWLOCK_INITIALIZER, .device_lock = PTHREAD_MUTEX_INITIALIZER }; 88 | 89 | int ve_open(void) 90 | { 91 | if (ve.fd != -1) 92 | return 0; 93 | 94 | struct ve_info info; 95 | 96 | ve.fd = open(DEVICE, O_RDWR); 97 | if (ve.fd == -1) 98 | return 0; 99 | 100 | if (ioctl(ve.fd, IOCTL_GET_ENV_INFO, (void *)(&info)) == -1) 101 | goto err; 102 | 103 | ve.regs = mmap(NULL, 0x800, PROT_READ | PROT_WRITE, MAP_SHARED, ve.fd, info.registers); 104 | if (ve.regs == MAP_FAILED) 105 | goto err; 106 | 107 | ve.first_memchunk.phys_addr = info.reserved_mem - PAGE_OFFSET; 108 | ve.first_memchunk.size = info.reserved_mem_size; 109 | 110 | ioctl(ve.fd, IOCTL_ENGINE_REQ, 0); 111 | ioctl(ve.fd, IOCTL_ENABLE_VE, 0); 112 | ioctl(ve.fd, IOCTL_SET_VE_FREQ, 320); 113 | ioctl(ve.fd, IOCTL_RESET_VE, 0); 114 | 115 | writel(0x00130007, ve.regs + VE_CTRL); 116 | 117 | ve.version = readl(ve.regs + VE_VERSION) >> 16; 118 | printf("[VDPAU SUNXI] VE version 0x%04x opened.\n", ve.version); 119 | 120 | return 1; 121 | 122 | err: 123 | close(ve.fd); 124 | ve.fd = -1; 125 | return 0; 126 | } 127 | 128 | void ve_close(void) 129 | { 130 | if (ve.fd == -1) 131 | return; 132 | 133 | ioctl(ve.fd, IOCTL_DISABLE_VE, 0); 134 | ioctl(ve.fd, IOCTL_ENGINE_REL, 0); 135 | 136 | munmap(ve.regs, 0x800); 137 | ve.regs = NULL; 138 | 139 | close(ve.fd); 140 | ve.fd = -1; 141 | } 142 | 143 | int ve_get_version(void) 144 | { 145 | return ve.version; 146 | } 147 | 148 | int ve_wait(int timeout) 149 | { 150 | if (ve.fd == -1) 151 | return 0; 152 | 153 | return ioctl(ve.fd, IOCTL_WAIT_VE, timeout); 154 | } 155 | 156 | void *ve_get(int engine, uint32_t flags) 157 | { 158 | if (pthread_mutex_lock(&ve.device_lock)) 159 | return NULL; 160 | 161 | writel(0x00130000 | (engine & 0xf) | (flags & ~0xf), ve.regs + VE_CTRL); 162 | 163 | return ve.regs; 164 | } 165 | 166 | void ve_put(void) 167 | { 168 | writel(0x00130007, ve.regs + VE_CTRL); 169 | pthread_mutex_unlock(&ve.device_lock); 170 | } 171 | 172 | void *ve_malloc(int size) 173 | { 174 | if (ve.fd == -1) 175 | return NULL; 176 | 177 | if (pthread_rwlock_wrlock(&ve.memory_lock)) 178 | return NULL; 179 | 180 | void *addr = NULL; 181 | 182 | size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); 183 | struct memchunk_t *c, *best_chunk = NULL; 184 | for (c = &ve.first_memchunk; c != NULL; c = c->next) 185 | { 186 | if(c->virt_addr == NULL && c->size >= size) 187 | { 188 | if (best_chunk == NULL || c->size < best_chunk->size) 189 | best_chunk = c; 190 | 191 | if (c->size == size) 192 | break; 193 | } 194 | } 195 | 196 | if (!best_chunk) 197 | goto out; 198 | 199 | int left_size = best_chunk->size - size; 200 | 201 | addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, ve.fd, best_chunk->phys_addr + PAGE_OFFSET); 202 | if (addr == MAP_FAILED) 203 | { 204 | addr = NULL; 205 | goto out; 206 | } 207 | 208 | best_chunk->virt_addr = addr; 209 | best_chunk->size = size; 210 | 211 | if (left_size > 0) 212 | { 213 | c = malloc(sizeof(struct memchunk_t)); 214 | c->phys_addr = best_chunk->phys_addr + size; 215 | c->size = left_size; 216 | c->virt_addr = NULL; 217 | c->next = best_chunk->next; 218 | best_chunk->next = c; 219 | } 220 | 221 | out: 222 | pthread_rwlock_unlock(&ve.memory_lock); 223 | return addr; 224 | } 225 | 226 | void ve_free(void *ptr) 227 | { 228 | if (ve.fd == -1) 229 | return; 230 | 231 | if (ptr == NULL) 232 | return; 233 | 234 | if (pthread_rwlock_wrlock(&ve.memory_lock)) 235 | return; 236 | 237 | struct memchunk_t *c; 238 | for (c = &ve.first_memchunk; c != NULL; c = c->next) 239 | { 240 | if (c->virt_addr == ptr) 241 | { 242 | munmap(ptr, c->size); 243 | c->virt_addr = NULL; 244 | break; 245 | } 246 | } 247 | 248 | for (c = &ve.first_memchunk; c != NULL; c = c->next) 249 | { 250 | if (c->virt_addr == NULL) 251 | { 252 | while (c->next != NULL && c->next->virt_addr == NULL) 253 | { 254 | struct memchunk_t *n = c->next; 255 | c->size += n->size; 256 | c->next = n->next; 257 | free(n); 258 | } 259 | } 260 | } 261 | 262 | pthread_rwlock_unlock(&ve.memory_lock); 263 | } 264 | 265 | uint32_t ve_virt2phys(void *ptr) 266 | { 267 | if (ve.fd == -1) 268 | return 0; 269 | 270 | if (pthread_rwlock_rdlock(&ve.memory_lock)) 271 | return 0; 272 | 273 | uint32_t addr = 0; 274 | 275 | struct memchunk_t *c; 276 | for (c = &ve.first_memchunk; c != NULL; c = c->next) 277 | { 278 | if (c->virt_addr == NULL) 279 | continue; 280 | 281 | if (c->virt_addr == ptr) 282 | { 283 | addr = c->phys_addr; 284 | break; 285 | } 286 | else if (ptr > c->virt_addr && ptr < (c->virt_addr + c->size)) 287 | { 288 | addr = c->phys_addr + (ptr - c->virt_addr); 289 | break; 290 | } 291 | } 292 | 293 | pthread_rwlock_unlock(&ve.memory_lock); 294 | return addr; 295 | } 296 | 297 | void ve_flush_cache(void *start, int len) 298 | { 299 | if (ve.fd == -1) 300 | return; 301 | 302 | struct cedarv_cache_range range = 303 | { 304 | .start = (int)start, 305 | .end = (int)(start + len) 306 | }; 307 | 308 | ioctl(ve.fd, IOCTL_FLUSH_CACHE, (void*)(&range)); 309 | } 310 | -------------------------------------------------------------------------------- /jpeg-test/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Proof of Concept JPEG decoder using Allwinners CedarX 3 | * 4 | * WARNING: Don't use on "production systems". This was made by reverse 5 | * engineering and might crash your system or destroy data! 6 | * It was made only for my personal use of testing the reverse engineered 7 | * things, so don't expect good code quality. It's far from complete and 8 | * might crash if the JPEG doesn't fit it's requirements! 9 | * 10 | * 11 | * 12 | * Copyright (c) 2013 Jens Kuske 13 | * 14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation; either version 2 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU General Public License 25 | * along with this program; if not, write to the Free Software 26 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 27 | * MA 02110-1301, USA. 28 | * 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include "jpeg.h" 41 | #include "ve.h" 42 | #include "disp.h" 43 | 44 | void set_quantization_tables(struct jpeg_t *jpeg, void *regs) 45 | { 46 | int i; 47 | for (i = 0; i < 64; i++) 48 | writel((uint32_t)(64 + i) << 8 | jpeg->quant[0]->coeff[i], regs + VE_MPEG_IQ_MIN_INPUT); 49 | for (i = 0; i < 64; i++) 50 | writel((uint32_t)(i) << 8 | jpeg->quant[1]->coeff[i], regs + VE_MPEG_IQ_MIN_INPUT); 51 | } 52 | 53 | void set_huffman_tables(struct jpeg_t *jpeg, void *regs) 54 | { 55 | uint32_t buffer[512]; 56 | memset(buffer, 0, 4*512); 57 | int i; 58 | for (i = 0; i < 4; i++) 59 | { 60 | if (jpeg->huffman[i]) 61 | { 62 | int j, sum, last; 63 | 64 | last = 0; 65 | sum = 0; 66 | for (j = 0; j < 16; j++) 67 | { 68 | ((uint8_t *)buffer)[i * 64 + 32 + j] = sum; 69 | sum += jpeg->huffman[i]->num[j]; 70 | if (jpeg->huffman[i]->num[j] != 0) 71 | last = j; 72 | } 73 | memcpy(&(buffer[256 + 64 * i]), jpeg->huffman[i]->codes, sum); 74 | sum = 0; 75 | for (j = 0; j <= last; j++) 76 | { 77 | ((uint16_t *)buffer)[i * 32 + j] = sum; 78 | sum += jpeg->huffman[i]->num[j]; 79 | sum *= 2; 80 | } 81 | for (j = last + 1; j < 16; j++) 82 | { 83 | ((uint16_t *)buffer)[i * 32 + j] = 0xffff; 84 | } 85 | } 86 | } 87 | 88 | for (i = 0; i < 512; i++) 89 | { 90 | writel(buffer[i], regs + VE_MPEG_RAM_WRITE_DATA); 91 | } 92 | } 93 | 94 | void set_format(struct jpeg_t *jpeg, void *regs) 95 | { 96 | uint8_t fmt = (jpeg->comp[0].samp_h << 4) | jpeg->comp[0].samp_v; 97 | 98 | switch (fmt) 99 | { 100 | case 0x11: 101 | writeb(0x1b, regs + VE_MPEG_TRIGGER + 0x3); 102 | break; 103 | case 0x21: 104 | writeb(0x13, regs + VE_MPEG_TRIGGER + 0x3); 105 | break; 106 | case 0x12: 107 | writeb(0x23, regs + VE_MPEG_TRIGGER + 0x3); 108 | break; 109 | case 0x22: 110 | writeb(0x03, regs + VE_MPEG_TRIGGER + 0x3); 111 | break; 112 | } 113 | } 114 | 115 | void set_size(struct jpeg_t *jpeg, void *regs) 116 | { 117 | uint16_t h = (jpeg->height - 1) / (8 * jpeg->comp[0].samp_v); 118 | uint16_t w = (jpeg->width - 1) / (8 * jpeg->comp[0].samp_h); 119 | writel((uint32_t)h << 16 | w, regs + VE_MPEG_JPEG_SIZE); 120 | } 121 | 122 | void output_ppm(FILE *file, struct jpeg_t *jpeg, uint8_t *luma_buffer, uint8_t *chroma_buffer) 123 | { 124 | fprintf(file, "P3\n%u %u\n255\n", jpeg->width, jpeg->height); 125 | int x, y, i = 0; 126 | for (y = 0; y < jpeg->height; y++) 127 | { 128 | for (x = 0; x < jpeg->width; x++) 129 | { 130 | // reordering and colorspace conversion should be done by Display Engine Frontend (DEFE) 131 | int cy = y / jpeg->comp[0].samp_v; 132 | float Y = *((uint8_t *)(luma_buffer + (x / 32) * 1024 + (x % 32) + ((y % 32) * 32) + ((y / 32) * (((jpeg->width + 31) / 32) * 1024)))); 133 | float Cb = *((uint8_t *)(chroma_buffer + (x / 32) * 1024 + ((x % 32) / 2 * 2) + ((cy % 32) * 32) + ((cy / 32) * (((jpeg->width + 31) / 32) * 1024)))) - 128.0; 134 | float Cr = *((uint8_t *)(chroma_buffer + (x / 32) * 1024 + ((x % 32) / 2 * 2 + 1) + ((cy % 32) * 32) + ((cy / 32) * (((jpeg->width + 31) / 32) * 1024)))) - 128.0; 135 | 136 | float R = Y + 1.402 * Cr; 137 | float G = Y - 0.344136 * Cb - 0.714136 * Cr; 138 | float B = Y + 1.772 * Cb; 139 | 140 | if (R > 255.0) R = 255.0; 141 | else if (R < 0.0) R = 0.0; 142 | 143 | if (G > 255.0) G = 255.0; 144 | else if (G < 0.0) G = 0.0; 145 | 146 | if (B > 255.0) B = 255.0; 147 | else if (B < 0.0) B = 0.0; 148 | 149 | fprintf(file, "%3u %3u %3u %c", (uint8_t)R, (uint8_t)G, (uint8_t)B, (++i % 5) ? ' ' : '\n'); 150 | } 151 | } 152 | fprintf(file, "\n"); 153 | } 154 | 155 | void decode_jpeg(struct jpeg_t *jpeg) 156 | { 157 | if (!ve_open()) 158 | err(EXIT_FAILURE, "Can't open VE"); 159 | 160 | int input_size =(jpeg->data_len + 65535) & ~65535; 161 | uint8_t *input_buffer = ve_malloc(input_size); 162 | int output_size = ((jpeg->width + 31) & ~31) * ((jpeg->height + 31) & ~31); 163 | uint8_t *luma_output = ve_malloc(output_size); 164 | uint8_t *chroma_output = ve_malloc(output_size); 165 | memcpy(input_buffer, jpeg->data, jpeg->data_len); 166 | ve_flush_cache(input_buffer, jpeg->data_len); 167 | 168 | // activate MPEG engine 169 | void *ve_regs = ve_get(VE_ENGINE_MPEG, 0); 170 | 171 | // set restart interval 172 | writel(jpeg->restart_interval, ve_regs + VE_MPEG_JPEG_RES_INT); 173 | 174 | // set JPEG format 175 | set_format(jpeg, ve_regs); 176 | 177 | // set output buffers (Luma / Croma) 178 | writel(ve_virt2phys(luma_output), ve_regs + VE_MPEG_ROT_LUMA); 179 | writel(ve_virt2phys(chroma_output), ve_regs + VE_MPEG_ROT_CHROMA); 180 | 181 | // set size 182 | set_size(jpeg, ve_regs); 183 | 184 | // ?? 185 | writel(0x00000000, ve_regs + VE_MPEG_SDROT_CTRL); 186 | 187 | // input end 188 | writel(ve_virt2phys(input_buffer) + input_size - 1, ve_regs + VE_MPEG_VLD_END); 189 | 190 | // ?? 191 | writel(0x0000007c, ve_regs + VE_MPEG_CTRL); 192 | 193 | // set input offset in bits 194 | writel(0 * 8, ve_regs + VE_MPEG_VLD_OFFSET); 195 | 196 | // set input length in bits 197 | writel(jpeg->data_len * 8, ve_regs + VE_MPEG_VLD_LEN); 198 | 199 | // set input buffer 200 | writel(ve_virt2phys(input_buffer) | 0x70000000, ve_regs + VE_MPEG_VLD_ADDR); 201 | 202 | // set Quantisation Table 203 | set_quantization_tables(jpeg, ve_regs); 204 | 205 | // set Huffman Table 206 | writel(0x00000000, ve_regs + VE_MPEG_RAM_WRITE_PTR); 207 | set_huffman_tables(jpeg, ve_regs); 208 | 209 | // start 210 | writeb(0x0e, ve_regs + VE_MPEG_TRIGGER); 211 | 212 | // wait for interrupt 213 | ve_wait(1); 214 | 215 | // clean interrupt flag (??) 216 | writel(0x0000c00f, ve_regs + VE_MPEG_STATUS); 217 | 218 | // stop MPEG engine 219 | ve_put(); 220 | 221 | //output_ppm(stdout, jpeg, output, output + (output_buf_size / 2)); 222 | 223 | if (!disp_open()) 224 | { 225 | fprintf(stderr, "Can't open /dev/disp\n"); 226 | return; 227 | } 228 | 229 | int color; 230 | switch ((jpeg->comp[0].samp_h << 4) | jpeg->comp[0].samp_v) 231 | { 232 | case 0x11: 233 | case 0x21: 234 | color = COLOR_YUV422; 235 | break; 236 | case 0x12: 237 | case 0x22: 238 | default: 239 | color = COLOR_YUV420; 240 | break; 241 | } 242 | 243 | disp_set_para(ve_virt2phys(luma_output), ve_virt2phys(chroma_output), 244 | color, jpeg->width, jpeg->height, 245 | 0, 0, 800, 600); 246 | 247 | getchar(); 248 | 249 | disp_close(); 250 | 251 | ve_free(input_buffer); 252 | ve_free(luma_output); 253 | ve_free(chroma_output); 254 | ve_close(); 255 | } 256 | 257 | int main(const int argc, const char **argv) 258 | { 259 | int in; 260 | struct stat s; 261 | uint8_t *data; 262 | 263 | if (argc < 2) 264 | { 265 | fprintf(stderr, "Usage: %s infile.jpg\n", argv[0]); 266 | exit(EXIT_FAILURE); 267 | } 268 | 269 | const char *filename = argv[1]; 270 | 271 | if ((in = open(filename, O_RDONLY)) == -1) 272 | err(EXIT_FAILURE, "%s", filename); 273 | 274 | if (fstat(in, &s) < 0) 275 | err(EXIT_FAILURE, "stat %s", filename); 276 | 277 | if (s.st_size == 0) 278 | errx(EXIT_FAILURE, "%s empty", filename); 279 | 280 | if ((data = mmap(NULL, s.st_size, PROT_READ, MAP_SHARED, in, 0)) == MAP_FAILED) 281 | err(EXIT_FAILURE, "mmap %s", filename); 282 | 283 | struct jpeg_t jpeg ; 284 | memset(&jpeg, 0, sizeof(jpeg)); 285 | if (!parse_jpeg(&jpeg, data, s.st_size)) 286 | warnx("Can't parse JPEG"); 287 | 288 | //dump_jpeg(&jpeg); 289 | decode_jpeg(&jpeg); 290 | 291 | munmap(data, s.st_size); 292 | close(in); 293 | 294 | return EXIT_SUCCESS; 295 | } 296 | -------------------------------------------------------------------------------- /mpeg-test/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Proof of Concept MPEG1/2 decoder using Allwinners CedarX 3 | * 4 | * WARNING: Don't use on "production systems". This was made by reverse 5 | * engineering and might crash your system or destroy data! 6 | * It was made only for my personal use of testing the reverse engineered 7 | * things, so don't expect good code quality. It's far from complete and 8 | * might crash if the MPEG doesn't fit it's requirements! 9 | * 10 | * 11 | * 12 | * Copyright (c) 2013 Jens Kuske 13 | * 14 | * This program is free software; you can redistribute it and/or modify 15 | * it under the terms of the GNU General Public License as published by 16 | * the Free Software Foundation; either version 2 of the License, or 17 | * (at your option) any later version. 18 | * 19 | * This program is distributed in the hope that it will be useful, 20 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | * GNU General Public License for more details. 23 | * 24 | * You should have received a copy of the GNU General Public License 25 | * along with this program; if not, write to the Free Software 26 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 27 | * MA 02110-1301, USA. 28 | * 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include "mpeg.h" 35 | #include "ve.h" 36 | #include "disp.h" 37 | 38 | static const uint8_t mpeg_default_intra_quant[64] = 39 | { 40 | 8, 16, 16, 19, 16, 19, 22, 22, 41 | 22, 22, 22, 22, 26, 24, 26, 27, 42 | 27, 27, 26, 26, 26, 26, 27, 27, 43 | 27, 29, 29, 29, 34, 34, 34, 29, 44 | 29, 29, 27, 27, 29, 29, 32, 32, 45 | 34, 34, 37, 38, 37, 35, 35, 34, 46 | 35, 38, 38, 40, 40, 40, 48, 48, 47 | 46, 46, 56, 56, 58, 69, 69, 83 48 | }; 49 | 50 | static const uint8_t mpeg_default_non_intra_quant[64] = 51 | { 52 | 16, 16, 16, 16, 16, 16, 16, 16, 53 | 16, 16, 16, 16, 16, 16, 16, 16, 54 | 16, 16, 16, 16, 16, 16, 16, 16, 55 | 16, 16, 16, 16, 16, 16, 16, 16, 56 | 16, 16, 16, 16, 16, 16, 16, 16, 57 | 16, 16, 16, 16, 16, 16, 16, 16, 58 | 16, 16, 16, 16, 16, 16, 16, 16, 59 | 16, 16, 16, 16, 16, 16, 16, 16 60 | }; 61 | 62 | static void set_quantization_tables(void * const regs, const uint8_t * const table1, const uint8_t * const table2) 63 | { 64 | int i; 65 | for (i = 0; i < 64; i++) 66 | writel((uint32_t)(64 + i) << 8 | table1[i], regs + VE_MPEG_IQ_MIN_INPUT); 67 | for (i = 0; i < 64; i++) 68 | writel((uint32_t)(i) << 8 | table2[i], regs + VE_MPEG_IQ_MIN_INPUT); 69 | } 70 | 71 | struct frame_t 72 | { 73 | void *luma_buffer; 74 | void *chroma_buffer; 75 | uint16_t width, height; 76 | int color; 77 | 78 | int ref_counter; 79 | }; 80 | 81 | struct frame_buffers_t 82 | { 83 | struct frame_t *output; 84 | struct frame_t *backward; 85 | struct frame_t *forward; 86 | }; 87 | 88 | void frame_show(struct frame_t *frame) 89 | { 90 | static int disp_initialized = 0; 91 | static int frame_id = 0; 92 | 93 | if (!disp_initialized) 94 | { 95 | if (!disp_open()) 96 | { 97 | fprintf(stderr, "Can't open /dev/disp\n"); 98 | return; 99 | } 100 | 101 | disp_set_para(ve_virt2phys(frame->luma_buffer), ve_virt2phys(frame->chroma_buffer), 102 | frame->color, frame->width, frame->height, 103 | 0, 0, 800, 600); 104 | 105 | disp_initialized = 1; 106 | } 107 | 108 | disp_new_frame(ve_virt2phys(frame->luma_buffer), ve_virt2phys(frame->chroma_buffer), 109 | frame_id++, 24000); 110 | } 111 | 112 | struct frame_t *frame_new(uint16_t width, uint16_t height, int color) 113 | { 114 | int size = ((width + 31) & ~31) * ((height + 31) & ~31); 115 | 116 | struct frame_t *frame = malloc(sizeof(struct frame_t)); 117 | frame->luma_buffer = ve_malloc(size); 118 | frame->chroma_buffer = ve_malloc(size); 119 | 120 | frame->width = width; 121 | frame->height = height; 122 | frame->color = color; 123 | 124 | frame->ref_counter = 1; 125 | 126 | return frame; 127 | } 128 | 129 | struct frame_t *frame_ref(struct frame_t *frame) 130 | { 131 | if (!frame) 132 | return NULL; 133 | 134 | frame->ref_counter++; 135 | 136 | return frame; 137 | } 138 | 139 | void frame_unref(struct frame_t *frame) 140 | { 141 | if (!frame) 142 | return; 143 | 144 | frame->ref_counter--; 145 | 146 | if (frame->ref_counter <= 0) 147 | { 148 | ve_free(frame->luma_buffer); 149 | ve_free(frame->chroma_buffer); 150 | free(frame); 151 | } 152 | } 153 | 154 | void decode_mpeg(struct frame_buffers_t *frame_buffers, const struct mpeg_t * const mpeg) 155 | { 156 | int input_size = (mpeg->len + 65535) & ~65535; 157 | uint8_t *input_buffer = ve_malloc(input_size); 158 | memcpy(input_buffer, mpeg->data, mpeg->len); 159 | ve_flush_cache(input_buffer, mpeg->len); 160 | 161 | // activate MPEG engine 162 | void *ve_regs = ve_get(VE_ENGINE_MPEG, 0); 163 | 164 | // set quantisation tables 165 | set_quantization_tables(ve_regs, mpeg_default_intra_quant, mpeg_default_non_intra_quant); 166 | 167 | // set size 168 | uint16_t width = (mpeg->width + 15) / 16; 169 | uint16_t height = (mpeg->height + 15) / 16; 170 | writel((width << 8) | height, ve_regs + VE_MPEG_SIZE); 171 | writel(((width * 16) << 16) | (height * 16), ve_regs + VE_MPEG_FRAME_SIZE); 172 | 173 | // set picture header 174 | uint32_t pic_header = 0x00000000; 175 | pic_header |= ((mpeg->picture_coding_type & 0xf) << 28); 176 | pic_header |= ((mpeg->f_code[0][0] & 0xf) << 24); 177 | pic_header |= ((mpeg->f_code[0][1] & 0xf) << 20); 178 | pic_header |= ((mpeg->f_code[1][0] & 0xf) << 16); 179 | pic_header |= ((mpeg->f_code[1][1] & 0xf) << 12); 180 | pic_header |= ((mpeg->intra_dc_precision & 0x3) << 10); 181 | pic_header |= ((mpeg->picture_structure & 0x3) << 8); 182 | pic_header |= ((mpeg->top_field_first & 0x1) << 7); 183 | pic_header |= ((mpeg->frame_pred_frame_dct & 0x1) << 6); 184 | pic_header |= ((mpeg->concealment_motion_vectors & 0x1) << 5); 185 | pic_header |= ((mpeg->q_scale_type & 0x1) << 4); 186 | pic_header |= ((mpeg->intra_vlc_format & 0x1) << 3); 187 | pic_header |= ((mpeg->alternate_scan & 0x1) << 2); 188 | pic_header |= ((mpeg->full_pel_forward_vector & 0x1) << 1); 189 | pic_header |= ((mpeg->full_pel_backward_vector & 0x1) << 0); 190 | writel(pic_header, ve_regs + VE_MPEG_PIC_HDR); 191 | 192 | // ?? 193 | writel(0x00000000, ve_regs + 0x100 + 0x10); 194 | 195 | // ?? 196 | writel(0x800001b8, ve_regs + VE_MPEG_CTRL); 197 | 198 | // ?? 199 | writel(0x00000000, ve_regs + 0x100 + 0xc4); 200 | 201 | // ?? 202 | writel(0x00000000, ve_regs + 0x100 + 0xc8); 203 | 204 | // set forward/backward predicion buffers 205 | if (mpeg->picture_coding_type == PCT_I || mpeg->picture_coding_type == PCT_P) 206 | { 207 | frame_unref(frame_buffers->forward); 208 | frame_buffers->forward = frame_ref(frame_buffers->backward); 209 | frame_unref(frame_buffers->backward); 210 | frame_buffers->backward = frame_ref(frame_buffers->output); 211 | } 212 | writel(ve_virt2phys(frame_buffers->forward->luma_buffer), ve_regs + VE_MPEG_FWD_LUMA); 213 | writel(ve_virt2phys(frame_buffers->forward->chroma_buffer), ve_regs + VE_MPEG_FWD_CHROMA); 214 | writel(ve_virt2phys(frame_buffers->backward->luma_buffer), ve_regs + VE_MPEG_BACK_LUMA); 215 | writel(ve_virt2phys(frame_buffers->backward->chroma_buffer), ve_regs + VE_MPEG_BACK_CHROMA); 216 | 217 | // set output buffers (Luma / Croma) 218 | writel(ve_virt2phys(frame_buffers->output->luma_buffer), ve_regs + VE_MPEG_REC_LUMA); 219 | writel(ve_virt2phys(frame_buffers->output->chroma_buffer), ve_regs + VE_MPEG_REC_CHROMA); 220 | writel(ve_virt2phys(frame_buffers->output->luma_buffer), ve_regs + VE_MPEG_ROT_LUMA); 221 | writel(ve_virt2phys(frame_buffers->output->chroma_buffer), ve_regs + VE_MPEG_ROT_CHROMA); 222 | 223 | // set input offset in bits 224 | writel((mpeg->pos - 4) * 8, ve_regs + VE_MPEG_VLD_OFFSET); 225 | 226 | // set input length in bits (+ little bit more, else it fails sometimes ??) 227 | writel((mpeg->len - (mpeg->pos - 4) + 16) * 8, ve_regs + VE_MPEG_VLD_LEN); 228 | 229 | // input end 230 | writel(ve_virt2phys(input_buffer) + input_size - 1, ve_regs + VE_MPEG_VLD_END); 231 | 232 | // set input buffer 233 | writel(ve_virt2phys(input_buffer) | 0x50000000, ve_regs + VE_MPEG_VLD_ADDR); 234 | 235 | // trigger 236 | writel((mpeg->type ? 0x02000000 : 0x01000000) | 0x8000000f, ve_regs + VE_MPEG_TRIGGER); 237 | 238 | // wait for interrupt 239 | ve_wait(1); 240 | 241 | // clean interrupt flag (??) 242 | writel(0x0000c00f, ve_regs + VE_MPEG_STATUS); 243 | 244 | // stop MPEG engine 245 | ve_put(); 246 | 247 | ve_free(input_buffer); 248 | } 249 | 250 | #define RING_BUFFER_SIZE (8) 251 | 252 | int main(int argc, char** argv) 253 | { 254 | AVFormatContext* avfmt_ctx = NULL; 255 | int video_stream; 256 | enum AVCodecID video_codec; 257 | 258 | if (argc < 2) 259 | { 260 | fprintf(stderr, "Usage: %s filename\n", argv[0]); 261 | exit(EXIT_FAILURE); 262 | } 263 | 264 | char *filename = argv[1]; 265 | 266 | av_register_all(); 267 | 268 | if (avformat_open_input(&avfmt_ctx, filename, NULL, NULL) < 0) 269 | { 270 | fprintf(stderr, "Could not open source file %s\n", filename); 271 | exit(1); 272 | } 273 | 274 | if (avformat_find_stream_info(avfmt_ctx, NULL) < 0) 275 | { 276 | fprintf(stderr, "Could not find stream information\n"); 277 | avformat_close_input(&avfmt_ctx); 278 | exit(1); 279 | } 280 | 281 | video_stream = av_find_best_stream(avfmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); 282 | if (video_stream < 0) 283 | { 284 | fprintf(stderr, "Could not find video stream in input file\n"); 285 | avformat_close_input(&avfmt_ctx); 286 | exit(1); 287 | } 288 | 289 | video_codec = avfmt_ctx->streams[video_stream]->codec->codec_id; 290 | 291 | if (video_codec != AV_CODEC_ID_MPEG1VIDEO && video_codec != AV_CODEC_ID_MPEG2VIDEO) 292 | { 293 | fprintf(stderr, "Can't handle codec %s\n", avcodec_get_name(video_codec)); 294 | avformat_close_input(&avfmt_ctx); 295 | exit(1); 296 | } 297 | 298 | AVPacket pkt; 299 | av_init_packet(&pkt); 300 | pkt.data = NULL; 301 | pkt.size = 0; 302 | 303 | struct mpeg_t mpeg; 304 | memset(&mpeg, 0, sizeof(mpeg)); 305 | if (video_codec == AV_CODEC_ID_MPEG1VIDEO) 306 | mpeg.type = MPEG1; 307 | else 308 | mpeg.type = MPEG2; 309 | 310 | if (!ve_open()) 311 | err(EXIT_FAILURE, "Can't open VE"); 312 | 313 | struct frame_buffers_t frame_buffers = { NULL, NULL, NULL }; 314 | 315 | unsigned int disp_frame = 0, gop_offset = 0, gop_frames = 0, last_gop = 0; 316 | struct frame_t *frames[RING_BUFFER_SIZE]; 317 | memset(frames, 0, sizeof(frames)); 318 | 319 | printf("Playing now... press Enter for next frame!\n"); 320 | 321 | while (av_read_frame(avfmt_ctx, &pkt) >= 0) 322 | { 323 | mpeg.data = pkt.data; 324 | mpeg.len = pkt.size; 325 | mpeg.pos = 0; 326 | 327 | if (pkt.stream_index == video_stream && parse_mpeg(&mpeg)) 328 | { 329 | // create output buffer 330 | frame_buffers.output = frame_new(mpeg.width, mpeg.height, COLOR_YUV420); 331 | if (!frame_buffers.backward) 332 | frame_buffers.backward = frame_ref(frame_buffers.output); 333 | if (!frame_buffers.forward) 334 | frame_buffers.forward = frame_ref(frame_buffers.output); 335 | 336 | // decode frame 337 | decode_mpeg(&frame_buffers, &mpeg); 338 | 339 | // simple frame reordering (not safe, only for testing) 340 | // count frames 341 | if (mpeg.gop > last_gop) 342 | { 343 | last_gop = mpeg.gop; 344 | gop_offset += gop_frames; 345 | gop_frames = 0; 346 | } 347 | gop_frames++; 348 | 349 | // save frame in ringbuffer 350 | if (frames[(gop_offset + mpeg.temporal_reference) % RING_BUFFER_SIZE] != NULL) 351 | { 352 | printf("Buffer overrun!\n"); 353 | frame_unref(frames[(gop_offset + mpeg.temporal_reference) % RING_BUFFER_SIZE]); 354 | } 355 | frames[(gop_offset + mpeg.temporal_reference) % RING_BUFFER_SIZE] = frame_buffers.output; 356 | 357 | // if we decoded a displayable frame, show it 358 | if (frames[disp_frame % RING_BUFFER_SIZE] != NULL) 359 | { 360 | frame_show(frames[disp_frame % RING_BUFFER_SIZE]); 361 | frame_unref(frames[(disp_frame - 2) % RING_BUFFER_SIZE]); 362 | frames[(disp_frame - 2) % RING_BUFFER_SIZE] = NULL; 363 | disp_frame++; 364 | getchar(); 365 | } 366 | 367 | } 368 | av_free_packet(&pkt); 369 | } 370 | 371 | // show left over frames 372 | while (disp_frame < gop_offset + gop_frames && frames[disp_frame % RING_BUFFER_SIZE] != NULL) 373 | { 374 | frame_show(frames[disp_frame % RING_BUFFER_SIZE]); 375 | frame_unref(frames[(disp_frame - 2) % RING_BUFFER_SIZE]); 376 | frames[(disp_frame - 2) % RING_BUFFER_SIZE] = NULL; 377 | disp_frame++; 378 | getchar(); 379 | } 380 | 381 | disp_close(); 382 | 383 | frame_unref(frames[(disp_frame - 2) % RING_BUFFER_SIZE]); 384 | frame_unref(frames[(disp_frame - 1) % RING_BUFFER_SIZE]); 385 | 386 | frame_unref(frame_buffers.forward); 387 | frame_unref(frame_buffers.backward); 388 | 389 | ve_close(); 390 | 391 | avformat_close_input(&avfmt_ctx); 392 | 393 | return 0; 394 | } 395 | -------------------------------------------------------------------------------- /h264enc/h264enc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 Jens Kuske 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, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 17 | * MA 02110-1301, USA. 18 | * 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include "h264enc.h" 25 | #include "ve.h" 26 | 27 | #define MSG(x) fprintf(stderr, "h264enc: " x "\n") 28 | 29 | #define ALIGN(x, a) (((x) + ((typeof(x))(a) - 1)) & ~((typeof(x))(a) - 1)) 30 | #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) 31 | #define DIV_ROUND_UP(n, d) (((n) + (d) - 1) / (d)) 32 | 33 | struct h264enc_internal { 34 | unsigned int mb_width, mb_height, mb_stride; 35 | unsigned int crop_right, crop_bottom; 36 | 37 | uint8_t *luma_buffer, *chroma_buffer; 38 | unsigned int input_buffer_size; 39 | enum color_format input_color_format; 40 | 41 | uint8_t *bytestream_buffer; 42 | unsigned int bytestream_buffer_size; 43 | unsigned int bytestream_length; 44 | 45 | struct h264enc_ref_pic { 46 | void *luma_buffer, *chroma_buffer; 47 | void *extra_buffer; /* unknown purpose, looks like smaller luma */ 48 | } ref_picture[2]; 49 | 50 | void *extra_buffer_line, *extra_buffer_frame; /* unknown purpose */ 51 | 52 | void *regs; 53 | 54 | unsigned int write_sps_pps; 55 | 56 | unsigned int profile_idc, level_idc, constraints; 57 | 58 | unsigned int entropy_coding_mode_flag; 59 | unsigned int pic_init_qp; 60 | 61 | unsigned int keyframe_interval; 62 | 63 | unsigned int current_frame_num; 64 | enum slice_type { SLICE_P = 0, SLICE_I = 2 } current_slice_type; 65 | 66 | }; 67 | 68 | static void put_bits(void* regs, uint32_t x, int num) 69 | { 70 | writel(x, regs + VE_AVC_BASIC_BITS); 71 | writel(0x1 | ((num & 0x1f) << 8), regs + VE_AVC_TRIGGER); 72 | /* again the problem, how to check for finish? */ 73 | } 74 | 75 | static void put_ue(void* regs, uint32_t x) 76 | { 77 | x++; 78 | put_bits(regs, x, (32 - __builtin_clz(x)) * 2 - 1); 79 | } 80 | 81 | static void put_se(void* regs, int x) 82 | { 83 | x = 2 * x - 1; 84 | x ^= (x >> 31); 85 | put_ue(regs, x); 86 | } 87 | 88 | static void put_start_code(void* regs, unsigned int nal_ref_idc, unsigned int nal_unit_type) 89 | { 90 | uint32_t tmp = readl(regs + VE_AVC_PARAM); 91 | 92 | /* disable emulation_prevention_three_byte */ 93 | writel(tmp | (0x1 << 31), regs + VE_AVC_PARAM); 94 | 95 | put_bits(regs, 0, 24); 96 | put_bits(regs, 0x100 | (nal_ref_idc << 5) | (nal_unit_type << 0), 16); 97 | 98 | writel(tmp, regs + VE_AVC_PARAM); 99 | } 100 | 101 | static void put_rbsp_trailing_bits(void* regs) 102 | { 103 | unsigned int cur_bs_len = readl(regs + VE_AVC_VLE_LENGTH); 104 | 105 | int num_zero_bits = 8 - ((cur_bs_len + 1) & 0x7); 106 | put_bits(regs, 1 << num_zero_bits, num_zero_bits + 1); 107 | } 108 | 109 | static void put_seq_parameter_set(h264enc *c) 110 | { 111 | put_start_code(c->regs, 3, 7); 112 | 113 | put_bits(c->regs, c->profile_idc, 8); 114 | put_bits(c->regs, c->constraints, 8); 115 | put_bits(c->regs, c->level_idc, 8); 116 | 117 | put_ue(c->regs, /* seq_parameter_set_id = */ 0); 118 | 119 | put_ue(c->regs, /* log2_max_frame_num_minus4 = */ 0); 120 | put_ue(c->regs, /* pic_order_cnt_type = */ 2); 121 | 122 | put_ue(c->regs, /* max_num_ref_frames = */ 1); 123 | put_bits(c->regs, /* gaps_in_frame_num_value_allowed_flag = */ 0, 1); 124 | 125 | put_ue(c->regs, c->mb_width - 1); 126 | put_ue(c->regs, c->mb_height - 1); 127 | 128 | put_bits(c->regs, /* frame_mbs_only_flag = */ 1, 1); 129 | 130 | put_bits(c->regs, /* direct_8x8_inference_flag = */ 0, 1); 131 | 132 | unsigned int frame_cropping_flag = c->crop_right || c->crop_bottom; 133 | put_bits(c->regs, frame_cropping_flag, 1); 134 | if (frame_cropping_flag) 135 | { 136 | put_ue(c->regs, 0); 137 | put_ue(c->regs, c->crop_right); 138 | put_ue(c->regs, 0); 139 | put_ue(c->regs, c->crop_bottom); 140 | } 141 | 142 | put_bits(c->regs, /* vui_parameters_present_flag = */ 0, 1); 143 | 144 | put_rbsp_trailing_bits(c->regs); 145 | } 146 | 147 | static void put_pic_parameter_set(h264enc *c) 148 | { 149 | put_start_code(c->regs, 3, 8); 150 | 151 | put_ue(c->regs, /* pic_parameter_set_id = */ 0); 152 | put_ue(c->regs, /* seq_parameter_set_id = */ 0); 153 | 154 | put_bits(c->regs, c->entropy_coding_mode_flag, 1); 155 | 156 | put_bits(c->regs, /* bottom_field_pic_order_in_frame_present_flag = */ 0, 1); 157 | put_ue(c->regs, /* num_slice_groups_minus1 = */ 0); 158 | 159 | put_ue(c->regs, /* num_ref_idx_l0_default_active_minus1 = */ 0); 160 | put_ue(c->regs, /* num_ref_idx_l1_default_active_minus1 = */ 0); 161 | 162 | put_bits(c->regs, /* weighted_pred_flag = */ 0, 1); 163 | put_bits(c->regs, /* weighted_bipred_idc = */ 0, 2); 164 | 165 | put_se(c->regs, (int)c->pic_init_qp - 26); 166 | put_se(c->regs, (int)c->pic_init_qp - 26); 167 | put_se(c->regs, /* chroma_qp_index_offset = */ 4); 168 | 169 | put_bits(c->regs, /* deblocking_filter_control_present_flag = */ 1, 1); 170 | put_bits(c->regs, /* constrained_intra_pred_flag = */ 0, 1); 171 | put_bits(c->regs, /* redundant_pic_cnt_present_flag = */ 0, 1); 172 | 173 | put_rbsp_trailing_bits(c->regs); 174 | } 175 | 176 | static void put_slice_header(h264enc *c) 177 | { 178 | if (c->current_slice_type == SLICE_I) 179 | put_start_code(c->regs, 3, 5); 180 | else 181 | put_start_code(c->regs, 2, 1); 182 | 183 | put_ue(c->regs, /* first_mb_in_slice = */ 0); 184 | put_ue(c->regs, c->current_slice_type); 185 | put_ue(c->regs, /* pic_parameter_set_id = */ 0); 186 | 187 | put_bits(c->regs, c->current_frame_num & 0xf, 4); 188 | 189 | if (c->current_slice_type == SLICE_I) 190 | put_ue(c->regs, /* idr_pic_id = */ 0); 191 | 192 | if (c->current_slice_type == SLICE_P) 193 | { 194 | put_bits(c->regs, /* num_ref_idx_active_override_flag = */ 0, 1); 195 | put_bits(c->regs, /* ref_pic_list_modification_flag_l0 = */ 0, 1); 196 | put_bits(c->regs, /* adaptive_ref_pic_marking_mode_flag = */ 0, 1); 197 | if (c->entropy_coding_mode_flag) 198 | put_ue(c->regs, /* cabac_init_idc = */ 0); 199 | } 200 | 201 | if (c->current_slice_type == SLICE_I) 202 | { 203 | put_bits(c->regs, /* no_output_of_prior_pics_flag = */ 0, 1); 204 | put_bits(c->regs, /* long_term_reference_flag = */ 0, 1); 205 | } 206 | 207 | put_se(c->regs, /* slice_qp_delta = */ 0); 208 | 209 | put_ue(c->regs, /* disable_deblocking_filter_idc = */ 0); 210 | put_se(c->regs, /* slice_alpha_c0_offset_div2 = */ 0); 211 | put_se(c->regs, /* slice_beta_offset_div2 = */ 0); 212 | } 213 | 214 | void h264enc_free(h264enc *c) 215 | { 216 | int i; 217 | 218 | ve_free(c->extra_buffer_line); 219 | ve_free(c->extra_buffer_frame); 220 | for (i = 0; i < 2; i++) 221 | { 222 | ve_free(c->ref_picture[i].luma_buffer); 223 | ve_free(c->ref_picture[i].extra_buffer); 224 | } 225 | ve_free(c->bytestream_buffer); 226 | ve_free(c->luma_buffer); 227 | free(c); 228 | } 229 | 230 | h264enc *h264enc_new(const struct h264enc_params *p) 231 | { 232 | h264enc *c; 233 | int i; 234 | 235 | /* check parameter validity */ 236 | if (!IS_ALIGNED(p->src_width, 16) || !IS_ALIGNED(p->src_height, 16) || 237 | !IS_ALIGNED(p->width, 2) || !IS_ALIGNED(p->height, 2) || 238 | p->width > p->src_width || p->height > p->src_height) 239 | { 240 | MSG("invalid picture size"); 241 | return NULL; 242 | } 243 | 244 | if (p->qp == 0 || p->qp > 47) 245 | { 246 | MSG("invalid QP"); 247 | return NULL; 248 | } 249 | 250 | if (p->src_format != H264_FMT_NV12 && p->src_format != H264_FMT_NV16) 251 | { 252 | MSG("invalid color format"); 253 | return NULL; 254 | } 255 | 256 | /* allocate memory for h264enc structure */ 257 | c = calloc(1, sizeof(*c)); 258 | if (c == NULL) 259 | { 260 | MSG("can't allocate h264enc data"); 261 | return NULL; 262 | } 263 | 264 | /* copy parameters */ 265 | c->mb_width = DIV_ROUND_UP(p->width, 16); 266 | c->mb_height = DIV_ROUND_UP(p->height, 16); 267 | c->mb_stride = p->src_width / 16; 268 | 269 | c->crop_right = (c->mb_width * 16 - p->width) / 2; 270 | c->crop_bottom = (c->mb_height * 16 - p->height) / 2; 271 | 272 | c->profile_idc = p->profile_idc; 273 | c->level_idc = p->level_idc; 274 | 275 | c->entropy_coding_mode_flag = p->entropy_coding_mode ? 1 : 0; 276 | c->pic_init_qp = p->qp; 277 | c->keyframe_interval = p->keyframe_interval; 278 | 279 | c->write_sps_pps = 1; 280 | c->current_frame_num = 0; 281 | 282 | /* allocate input buffer */ 283 | c->input_color_format = p->src_format; 284 | switch (c->input_color_format) 285 | { 286 | case H264_FMT_NV12: 287 | c->input_buffer_size = p->src_width * (p->src_height + p->src_height / 2); 288 | break; 289 | case H264_FMT_NV16: 290 | c->input_buffer_size = p->src_width * p->src_height * 2; 291 | break; 292 | } 293 | 294 | c->luma_buffer = ve_malloc(c->input_buffer_size); 295 | if (c->luma_buffer == NULL) 296 | goto nomem; 297 | 298 | c->chroma_buffer = c->luma_buffer + p->src_width * p->src_height; 299 | 300 | /* allocate bytestream output buffer */ 301 | c->bytestream_buffer_size = 1 * 1024 * 1024; 302 | c->bytestream_buffer = ve_malloc(c->bytestream_buffer_size); 303 | if (c->bytestream_buffer == NULL) 304 | goto nomem; 305 | 306 | /* allocate reference picture memory */ 307 | unsigned int luma_size = ALIGN(c->mb_width * 16, 32) * ALIGN(c->mb_height * 16, 32); 308 | unsigned int chroma_size = ALIGN(c->mb_width * 16, 32) * ALIGN(c->mb_height * 8, 32); 309 | for (i = 0; i < 2; i++) 310 | { 311 | c->ref_picture[i].luma_buffer = ve_malloc(luma_size + chroma_size); 312 | c->ref_picture[i].chroma_buffer = c->ref_picture[i].luma_buffer + luma_size; 313 | c->ref_picture[i].extra_buffer = ve_malloc(luma_size / 4); 314 | if (c->ref_picture[i].luma_buffer == NULL || c->ref_picture[i].extra_buffer == NULL) 315 | goto nomem; 316 | } 317 | 318 | /* allocate unknown purpose buffers */ 319 | c->extra_buffer_frame = ve_malloc(ALIGN(c->mb_width, 4) * c->mb_height * 8); 320 | c->extra_buffer_line = ve_malloc(c->mb_width * 32); 321 | if (c->extra_buffer_frame == NULL || c->extra_buffer_line == NULL) 322 | goto nomem; 323 | 324 | return c; 325 | 326 | nomem: 327 | MSG("can't allocate VE memory"); 328 | h264enc_free(c); 329 | return NULL; 330 | } 331 | 332 | void *h264enc_get_input_buffer(const h264enc *c) 333 | { 334 | return c->luma_buffer; 335 | } 336 | 337 | void *h264enc_get_bytestream_buffer(const h264enc *c) 338 | { 339 | return c->bytestream_buffer; 340 | } 341 | 342 | unsigned int h264enc_get_bytestream_length(const h264enc *c) 343 | { 344 | return c->bytestream_length; 345 | } 346 | 347 | int h264enc_encode_picture(h264enc *c) 348 | { 349 | c->current_slice_type = c->current_frame_num ? SLICE_P : SLICE_I; 350 | 351 | c->regs = ve_get(VE_ENGINE_AVC, 0); 352 | 353 | /* flush buffers (output because otherwise we might read old data later) */ 354 | ve_flush_cache(c->bytestream_buffer, c->bytestream_buffer_size); 355 | ve_flush_cache(c->luma_buffer, c->input_buffer_size); 356 | 357 | /* set output buffer */ 358 | writel(0x0, c->regs + VE_AVC_VLE_OFFSET); 359 | writel(ve_virt2phys(c->bytestream_buffer), c->regs + VE_AVC_VLE_ADDR); 360 | writel(ve_virt2phys(c->bytestream_buffer) + c->bytestream_buffer_size - 1, c->regs + VE_AVC_VLE_END); 361 | writel(c->bytestream_buffer_size * 8, c->regs + VE_AVC_VLE_MAX); 362 | 363 | /* write headers */ 364 | if (c->write_sps_pps) 365 | { 366 | put_seq_parameter_set(c); 367 | put_pic_parameter_set(c); 368 | c->write_sps_pps = 0; 369 | } 370 | put_slice_header(c); 371 | 372 | /* set input size */ 373 | writel(c->mb_stride << 16, c->regs + VE_ISP_INPUT_STRIDE); 374 | writel((c->mb_width << 16) | (c->mb_height << 0), c->regs + VE_ISP_INPUT_SIZE); 375 | 376 | /* set input format */ 377 | writel(c->input_color_format << 29, c->regs + VE_ISP_CTRL); 378 | 379 | /* set input buffer */ 380 | writel(ve_virt2phys(c->luma_buffer), c->regs + VE_ISP_INPUT_LUMA); 381 | writel(ve_virt2phys(c->chroma_buffer), c->regs + VE_ISP_INPUT_CHROMA); 382 | 383 | /* set reconstruction buffers */ 384 | struct h264enc_ref_pic *ref_pic = &c->ref_picture[c->current_frame_num % 2]; 385 | writel(ve_virt2phys(ref_pic->luma_buffer), c->regs + VE_AVC_REC_LUMA); 386 | writel(ve_virt2phys(ref_pic->chroma_buffer), c->regs + VE_AVC_REC_CHROMA); 387 | writel(ve_virt2phys(ref_pic->extra_buffer), c->regs + VE_AVC_REC_SLUMA); 388 | 389 | /* set reference buffers */ 390 | if (c->current_slice_type != SLICE_I) 391 | { 392 | ref_pic = &c->ref_picture[(c->current_frame_num + 1) % 2]; 393 | writel(ve_virt2phys(ref_pic->luma_buffer), c->regs + VE_AVC_REF_LUMA); 394 | writel(ve_virt2phys(ref_pic->chroma_buffer), c->regs + VE_AVC_REF_CHROMA); 395 | writel(ve_virt2phys(ref_pic->extra_buffer), c->regs + VE_AVC_REF_SLUMA); 396 | } 397 | 398 | /* set unknown purpose buffers */ 399 | writel(ve_virt2phys(c->extra_buffer_line), c->regs + VE_AVC_MB_INFO); 400 | writel(ve_virt2phys(c->extra_buffer_frame), c->regs + VE_AVC_UNK_BUF); 401 | 402 | /* enable interrupt and clear status flags */ 403 | writel(readl(c->regs + VE_AVC_CTRL) | 0xf, c->regs + VE_AVC_CTRL); 404 | writel(readl(c->regs + VE_AVC_STATUS) | 0x7, c->regs + VE_AVC_STATUS); 405 | 406 | /* set encoding parameters */ 407 | uint32_t params = 0x0; 408 | if (c->entropy_coding_mode_flag) 409 | params |= 0x100; 410 | if (c->current_slice_type == SLICE_P) 411 | params |= 0x10; 412 | writel(params, c->regs + VE_AVC_PARAM); 413 | writel((4 << 16) | (c->pic_init_qp << 8) | c->pic_init_qp, c->regs + VE_AVC_QP); 414 | writel(0x00000104, c->regs + VE_AVC_MOTION_EST); 415 | 416 | /* trigger encoding */ 417 | writel(0x8, c->regs + VE_AVC_TRIGGER); 418 | ve_wait(1); 419 | 420 | /* check result */ 421 | uint32_t status = readl(c->regs + VE_AVC_STATUS); 422 | writel(status, c->regs + VE_AVC_STATUS); 423 | 424 | /* save bytestream length */ 425 | c->bytestream_length = readl(c->regs + VE_AVC_VLE_LENGTH) / 8; 426 | 427 | /* next frame */ 428 | c->current_frame_num++; 429 | if (c->current_frame_num >= c->keyframe_interval) 430 | c->current_frame_num = 0; 431 | 432 | ve_put(); 433 | 434 | return (status & 0x3) == 0x1; 435 | } 436 | -------------------------------------------------------------------------------- /common/sunxi_disp_ioctl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007-2012 Allwinner Technology Co., Ltd. 3 | * 4 | * This program is free software; you can redistribute it and/or 5 | * modify it under the terms of the GNU General Public License as 6 | * published by the Free Software Foundation; either version 2 of 7 | * the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program; if not, write to the Free Software 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 17 | * MA 02111-1307 USA 18 | */ 19 | 20 | #ifndef __SUNXI_DISP_IOCTL_H__ 21 | #define __SUNXI_DISP_IOCTL_H__ 22 | 23 | #define __bool signed char 24 | #define __u32 uint32_t 25 | #define __u8 uint8_t 26 | #define __s32 int32_t 27 | #define __u16 uint16_t 28 | 29 | /* for tracking the ioctls API/ABI */ 30 | #define SUNXI_DISP_VERSION_MAJOR 1 31 | #define SUNXI_DISP_VERSION_MINOR 0 32 | 33 | #define SUNXI_DISP_VERSION ((SUNXI_DISP_VERSION_MAJOR << 16) | SUNXI_DISP_VERSION_MINOR) 34 | #define SUNXI_DISP_VERSION_MAJOR_GET(x) (((x) >> 16) & 0x7FFF) 35 | #define SUNXI_DISP_VERSION_MINOR_GET(x) ((x) & 0xFFFF) 36 | 37 | typedef struct { 38 | __u8 alpha; 39 | __u8 red; 40 | __u8 green; 41 | __u8 blue; 42 | } __disp_color_t; 43 | typedef struct { 44 | __s32 x; 45 | __s32 y; 46 | __u32 width; 47 | __u32 height; 48 | } __disp_rect_t; 49 | typedef struct { 50 | __u32 width; 51 | __u32 height; 52 | } __disp_rectsz_t; 53 | typedef struct { 54 | __s32 x; 55 | __s32 y; 56 | } __disp_pos_t; 57 | 58 | typedef enum { 59 | DISP_FORMAT_1BPP = 0x0, 60 | DISP_FORMAT_2BPP = 0x1, 61 | DISP_FORMAT_4BPP = 0x2, 62 | DISP_FORMAT_8BPP = 0x3, 63 | DISP_FORMAT_RGB655 = 0x4, 64 | DISP_FORMAT_RGB565 = 0x5, 65 | DISP_FORMAT_RGB556 = 0x6, 66 | DISP_FORMAT_ARGB1555 = 0x7, 67 | DISP_FORMAT_RGBA5551 = 0x8, 68 | DISP_FORMAT_ARGB888 = 0x9, /* alpha padding to 0xff */ 69 | DISP_FORMAT_ARGB8888 = 0xa, 70 | DISP_FORMAT_RGB888 = 0xb, 71 | DISP_FORMAT_ARGB4444 = 0xc, 72 | 73 | DISP_FORMAT_YUV444 = 0x10, 74 | DISP_FORMAT_YUV422 = 0x11, 75 | DISP_FORMAT_YUV420 = 0x12, 76 | DISP_FORMAT_YUV411 = 0x13, 77 | DISP_FORMAT_CSIRGB = 0x14, 78 | } __disp_pixel_fmt_t; 79 | 80 | typedef enum { 81 | /* interleaved,1 address */ 82 | DISP_MOD_INTERLEAVED = 0x1, 83 | /* 84 | * No macroblock plane mode, 3 address, RGB/YUV each channel were stored 85 | */ 86 | DISP_MOD_NON_MB_PLANAR = 0x0, 87 | /* No macroblock UV packaged mode, 2 address, Y and UV were stored */ 88 | DISP_MOD_NON_MB_UV_COMBINED = 0x2, 89 | /* Macroblock plane mode, 3 address,RGB/YUV each channel were stored */ 90 | DISP_MOD_MB_PLANAR = 0x4, 91 | /* Macroblock UV packaged mode, 2 address, Y and UV were stored */ 92 | DISP_MOD_MB_UV_COMBINED = 0x6, 93 | } __disp_pixel_mod_t; 94 | 95 | typedef enum { 96 | /* for interleave argb8888 */ 97 | DISP_SEQ_ARGB = 0x0, /* A at a high level */ 98 | DISP_SEQ_BGRA = 0x2, 99 | 100 | /* for interleaved yuv422 */ 101 | DISP_SEQ_UYVY = 0x3, 102 | DISP_SEQ_YUYV = 0x4, 103 | DISP_SEQ_VYUY = 0x5, 104 | DISP_SEQ_YVYU = 0x6, 105 | 106 | /* for interleaved yuv444 */ 107 | DISP_SEQ_AYUV = 0x7, 108 | DISP_SEQ_VUYA = 0x8, 109 | 110 | /* for uv_combined yuv420 */ 111 | DISP_SEQ_UVUV = 0x9, 112 | DISP_SEQ_VUVU = 0xa, 113 | 114 | /* for 16bpp rgb */ 115 | DISP_SEQ_P10 = 0xd, /* p1 high */ 116 | DISP_SEQ_P01 = 0xe, /* p0 high */ 117 | 118 | /* for planar format or 8bpp rgb */ 119 | DISP_SEQ_P3210 = 0xf, /* p3 high */ 120 | DISP_SEQ_P0123 = 0x10, /* p0 high */ 121 | 122 | /* for 4bpp rgb */ 123 | DISP_SEQ_P76543210 = 0x11, 124 | DISP_SEQ_P67452301 = 0x12, 125 | DISP_SEQ_P10325476 = 0x13, 126 | DISP_SEQ_P01234567 = 0x14, 127 | 128 | /* for 2bpp rgb */ 129 | /* 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0 */ 130 | DISP_SEQ_2BPP_BIG_BIG = 0x15, 131 | /* 12,13,14,15,8,9,10,11,4,5,6,7,0,1,2,3 */ 132 | DISP_SEQ_2BPP_BIG_LITTER = 0x16, 133 | /* 3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12 */ 134 | DISP_SEQ_2BPP_LITTER_BIG = 0x17, 135 | /* 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ 136 | DISP_SEQ_2BPP_LITTER_LITTER = 0x18, 137 | 138 | /* for 1bpp rgb */ 139 | /* 140 | * 31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16, 141 | * 15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 142 | */ 143 | DISP_SEQ_1BPP_BIG_BIG = 0x19, 144 | /* 145 | * 24,25,26,27,28,29,30,31,16,17,18,19,20,21,22,23, 146 | * 8, 9,10,11,12,13,14,15, 0, 1, 2, 3, 4, 5, 6, 7 147 | */ 148 | DISP_SEQ_1BPP_BIG_LITTER = 0x1a, 149 | /* 150 | * 7, 6, 5, 4, 3, 2, 1, 0,15,14,13,12,11,10, 9, 8, 151 | * 23,22,21,20,19,18,17,16,31,30,29,28,27,26,25,24 152 | */ 153 | DISP_SEQ_1BPP_LITTER_BIG = 0x1b, 154 | /* 155 | * 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15, 156 | * 16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 157 | */ 158 | DISP_SEQ_1BPP_LITTER_LITTER = 0x1c, 159 | } __disp_pixel_seq_t; 160 | 161 | typedef enum { 162 | DISP_3D_SRC_MODE_TB = 0x0, /* top bottom */ 163 | DISP_3D_SRC_MODE_FP = 0x1, /* frame packing */ 164 | DISP_3D_SRC_MODE_SSF = 0x2, /* side by side full */ 165 | DISP_3D_SRC_MODE_SSH = 0x3, /* side by side half */ 166 | DISP_3D_SRC_MODE_LI = 0x4, /* line interleaved */ 167 | } __disp_3d_src_mode_t; 168 | 169 | typedef enum { 170 | DISP_3D_OUT_MODE_CI_1 = 0x5, /* column interlaved 1 */ 171 | DISP_3D_OUT_MODE_CI_2 = 0x6, /* column interlaved 2 */ 172 | DISP_3D_OUT_MODE_CI_3 = 0x7, /* column interlaved 3 */ 173 | DISP_3D_OUT_MODE_CI_4 = 0x8, /* column interlaved 4 */ 174 | DISP_3D_OUT_MODE_LIRGB = 0x9, /* line interleaved rgb */ 175 | 176 | DISP_3D_OUT_MODE_TB = 0x0, /* top bottom */ 177 | DISP_3D_OUT_MODE_FP = 0x1, /* frame packing */ 178 | DISP_3D_OUT_MODE_SSF = 0x2, /* side by side full */ 179 | DISP_3D_OUT_MODE_SSH = 0x3, /* side by side half */ 180 | DISP_3D_OUT_MODE_LI = 0x4, /* line interleaved */ 181 | DISP_3D_OUT_MODE_FA = 0xa, /* field alternative */ 182 | } __disp_3d_out_mode_t; 183 | 184 | typedef enum { 185 | DISP_BT601 = 0, 186 | DISP_BT709 = 1, 187 | DISP_YCC = 2, 188 | DISP_VXYCC = 3, 189 | } __disp_cs_mode_t; 190 | 191 | typedef enum { 192 | DISP_COLOR_RANGE_16_255 = 0, 193 | DISP_COLOR_RANGE_0_255 = 1, 194 | DISP_COLOR_RANGE_16_235 = 2, 195 | } __disp_color_range_t; 196 | 197 | typedef enum { 198 | DISP_OUTPUT_TYPE_NONE = 0, 199 | DISP_OUTPUT_TYPE_LCD = 1, 200 | DISP_OUTPUT_TYPE_TV = 2, 201 | DISP_OUTPUT_TYPE_HDMI = 4, 202 | DISP_OUTPUT_TYPE_VGA = 8, 203 | } __disp_output_type_t; 204 | 205 | typedef enum { 206 | DISP_TV_NONE = 0, 207 | DISP_TV_CVBS = 1, 208 | DISP_TV_YPBPR = 2, 209 | DISP_TV_SVIDEO = 4, 210 | } __disp_tv_output_t; 211 | 212 | typedef enum { 213 | DISP_TV_MOD_480I = 0, 214 | DISP_TV_MOD_576I = 1, 215 | DISP_TV_MOD_480P = 2, 216 | DISP_TV_MOD_576P = 3, 217 | DISP_TV_MOD_720P_50HZ = 4, 218 | DISP_TV_MOD_720P_60HZ = 5, 219 | DISP_TV_MOD_1080I_50HZ = 6, 220 | DISP_TV_MOD_1080I_60HZ = 7, 221 | DISP_TV_MOD_1080P_24HZ = 8, 222 | DISP_TV_MOD_1080P_50HZ = 9, 223 | DISP_TV_MOD_1080P_60HZ = 0xa, 224 | DISP_TV_MOD_1080P_24HZ_3D_FP = 0x17, 225 | DISP_TV_MOD_720P_50HZ_3D_FP = 0x18, 226 | DISP_TV_MOD_720P_60HZ_3D_FP = 0x19, 227 | DISP_TV_MOD_PAL = 0xb, 228 | DISP_TV_MOD_PAL_SVIDEO = 0xc, 229 | DISP_TV_MOD_NTSC = 0xe, 230 | DISP_TV_MOD_NTSC_SVIDEO = 0xf, 231 | DISP_TV_MOD_PAL_M = 0x11, 232 | DISP_TV_MOD_PAL_M_SVIDEO = 0x12, 233 | DISP_TV_MOD_PAL_NC = 0x14, 234 | DISP_TV_MOD_PAL_NC_SVIDEO = 0x15, 235 | 236 | DISP_TV_MOD_H1360_V768_60HZ = 0x1a, 237 | DISP_TV_MOD_H1280_V1024_60HZ = 0x1b, 238 | 239 | DISP_TV_MODE_NUM = 0x1c, 240 | 241 | /* Reserved, do not use in fex files */ 242 | DISP_TV_MODE_EDID = 0xff 243 | } __disp_tv_mode_t; 244 | 245 | typedef enum { 246 | DISP_TV_DAC_SRC_COMPOSITE = 0, 247 | DISP_TV_DAC_SRC_LUMA = 1, 248 | DISP_TV_DAC_SRC_CHROMA = 2, 249 | DISP_TV_DAC_SRC_Y = 4, 250 | DISP_TV_DAC_SRC_PB = 5, 251 | DISP_TV_DAC_SRC_PR = 6, 252 | DISP_TV_DAC_SRC_NONE = 7, 253 | } __disp_tv_dac_source; 254 | 255 | typedef enum { 256 | DISP_VGA_H1680_V1050 = 0, 257 | DISP_VGA_H1440_V900 = 1, 258 | DISP_VGA_H1360_V768 = 2, 259 | DISP_VGA_H1280_V1024 = 3, 260 | DISP_VGA_H1024_V768 = 4, 261 | DISP_VGA_H800_V600 = 5, 262 | DISP_VGA_H640_V480 = 6, 263 | DISP_VGA_H1440_V900_RB = 7, /* not support yet */ 264 | DISP_VGA_H1680_V1050_RB = 8, /* not support yet */ 265 | DISP_VGA_H1920_V1080_RB = 9, 266 | DISP_VGA_H1920_V1080 = 0xa, 267 | DISP_VGA_H1280_V720 = 0xb, 268 | DISP_VGA_MODE_NUM = 0xc, 269 | } __disp_vga_mode_t; 270 | 271 | typedef enum { 272 | DISP_LCDC_SRC_DE_CH1 = 0, 273 | DISP_LCDC_SRC_DE_CH2 = 1, 274 | DISP_LCDC_SRC_DMA = 2, 275 | DISP_LCDC_SRC_WHITE = 3, 276 | DISP_LCDC_SRC_BLACK = 4, 277 | DISP_LCDC_SRC_BLUT = 5, 278 | } __disp_lcdc_src_t; 279 | 280 | typedef enum { 281 | DISP_LAYER_WORK_MODE_NORMAL = 0, /* normal work mode */ 282 | DISP_LAYER_WORK_MODE_PALETTE = 1, /* palette work mode */ 283 | /* internal frame buffer work mode */ 284 | DISP_LAYER_WORK_MODE_INTER_BUF = 2, 285 | DISP_LAYER_WORK_MODE_GAMMA = 3, /* gamma correction work mode */ 286 | DISP_LAYER_WORK_MODE_SCALER = 4, /* scaler work mode */ 287 | } __disp_layer_work_mode_t; 288 | 289 | typedef enum { 290 | DISP_VIDEO_NATUAL = 0, 291 | DISP_VIDEO_SOFT = 1, 292 | DISP_VIDEO_VERYSOFT = 2, 293 | DISP_VIDEO_SHARP = 3, 294 | DISP_VIDEO_VERYSHARP = 4 295 | } __disp_video_smooth_t; 296 | 297 | typedef enum { 298 | DISP_HWC_MOD_H32_V32_8BPP = 0, 299 | DISP_HWC_MOD_H64_V64_2BPP = 1, 300 | DISP_HWC_MOD_H64_V32_4BPP = 2, 301 | DISP_HWC_MOD_H32_V64_4BPP = 3, 302 | } __disp_hwc_mode_t; 303 | 304 | typedef enum { 305 | DISP_EXIT_MODE_CLEAN_ALL = 0, 306 | DISP_EXIT_MODE_CLEAN_PARTLY = 1, /* only clean interrupt temply */ 307 | } __disp_exit_mode_t; 308 | 309 | typedef enum { /* only for debug!!! */ 310 | DISP_REG_SCALER0 = 0, 311 | DISP_REG_SCALER1 = 1, 312 | DISP_REG_IMAGE0 = 2, 313 | DISP_REG_IMAGE1 = 3, 314 | DISP_REG_LCDC0 = 4, 315 | DISP_REG_LCDC1 = 5, 316 | DISP_REG_TVEC0 = 6, 317 | DISP_REG_TVEC1 = 7, 318 | DISP_REG_CCMU = 8, 319 | DISP_REG_PIOC = 9, 320 | DISP_REG_PWM = 10, 321 | } __disp_reg_index_t; 322 | 323 | typedef struct { 324 | /* 325 | * The way these are treated today, these are physical addresses. Are 326 | * there any actual userspace applications out there that use this? 327 | * -- libv. 328 | */ 329 | /* 330 | * the contents of the frame buffer address for rgb type only addr[0] 331 | * valid 332 | */ 333 | __u32 addr[3]; 334 | __disp_rectsz_t size; /* unit is pixel */ 335 | __disp_pixel_fmt_t format; 336 | __disp_pixel_seq_t seq; 337 | __disp_pixel_mod_t mode; 338 | /* 339 | * blue red color swap flag, FALSE:RGB; TRUE:BGR,only used in rgb format 340 | */ 341 | __bool br_swap; 342 | __disp_cs_mode_t cs_mode; /* color space */ 343 | __bool b_trd_src; /* if 3d source, used for scaler mode layer */ 344 | /* source 3d mode, used for scaler mode layer */ 345 | __disp_3d_src_mode_t trd_mode; 346 | __u32 trd_right_addr[3]; /* used when in frame packing 3d mode */ 347 | } __disp_fb_t; 348 | 349 | typedef struct { 350 | __disp_layer_work_mode_t mode; /* layer work mode */ 351 | __bool b_from_screen; 352 | /* 353 | * layer pipe,0/1,if in scaler mode, scaler0 must be pipe0, 354 | * scaler1 must be pipe1 355 | */ 356 | __u8 pipe; 357 | /* 358 | * layer priority,can get layer prio,but never set layer prio. 359 | * From bottom to top, priority from low to high 360 | */ 361 | __u8 prio; 362 | __bool alpha_en; /* layer global alpha enable */ 363 | __u16 alpha_val; /* layer global alpha value */ 364 | __bool ck_enable; /* layer color key enable */ 365 | /* framebuffer source window,only care x,y if is not scaler mode */ 366 | __disp_rect_t src_win; 367 | __disp_rect_t scn_win; /* screen window */ 368 | __disp_fb_t fb; /* framebuffer */ 369 | __bool b_trd_out; /* if output 3d mode, used for scaler mode layer */ 370 | /* output 3d mode, used for scaler mode layer */ 371 | __disp_3d_out_mode_t out_trd_mode; 372 | } __disp_layer_info_t; 373 | 374 | typedef struct { 375 | __disp_color_t ck_max; 376 | __disp_color_t ck_min; 377 | /* 378 | * 0/1:always match; 379 | * 2:match if min<=color<=max; 380 | * 3:match if color>max or color