carlink_video.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #include <string.h>
  2. #include <stdint.h>
  3. #include <stdio.h>
  4. #include "carlink_video.h"
  5. #include "mfcapi.h"
  6. #include "lcd.h"
  7. #include "pxp.h"
  8. #include "cp15/cp15.h"
  9. #include "timer.h"
  10. #include "task.h"
  11. #include "semphr.h"
  12. #include "os_adapt.h"
  13. #include "ff_stdio.h"
  14. #include "video_buf.h"
  15. static List_t frame_free_list;
  16. static List_t frame_ready_list;
  17. static video_frame_s h264_frame_fifos[H264_FRAME_FIFO_COUNT];
  18. static char* h264_buf = NULL;
  19. static SemaphoreHandle_t frame_list_mutex = NULL;
  20. static TaskHandle_t dec_h264_handle;
  21. static QueueHandle_t h264_frame_queue;
  22. static uint8_t g_init_flag = 0;
  23. static uint8_t g_video_start = 0;
  24. static int g_disp_x = 0, g_disp_y = 0, g_disp_width = LCD_WIDTH, g_disp_height = LCD_HEIGHT;
  25. static int g_video_width = LCD_WIDTH, g_video_height = LCD_HEIGHT, g_video_fps = 30;
  26. static int g_hide_carlink_flag = 0;
  27. void set_carlink_video_info(int w, int h, int fps)
  28. {
  29. g_video_width = w;
  30. g_video_height = h;
  31. g_video_fps = fps;
  32. }
  33. int get_carlink_video_width()
  34. {
  35. return g_video_width;
  36. }
  37. int get_carlink_video_height()
  38. {
  39. return g_video_height;
  40. }
  41. int get_carlink_video_fps()
  42. {
  43. return g_video_fps;
  44. }
  45. void set_carlink_display_info(int x, int y, int w, int h)
  46. {
  47. g_disp_x = x;
  48. g_disp_y = y;
  49. g_disp_width = w;
  50. g_disp_height = h;
  51. }
  52. static void h264_frame_list_reset()
  53. {
  54. video_frame_s *buffer;
  55. int i;
  56. buffer = (video_frame_s *)h264_frame_fifos;
  57. vListInitialise(&frame_free_list);
  58. vListInitialise(&frame_ready_list);
  59. for(i = 0; i < H264_FRAME_FIFO_COUNT; i++) {
  60. buffer->buf = (char *)(((unsigned int)h264_buf + i * H264_FRAME_BUF_SIZE));
  61. buffer->cur = buffer->buf;
  62. buffer->frame_id = i;
  63. buffer->len = 0;
  64. vListInitialiseItem(&buffer->entry);
  65. vListInsertEnd(&frame_free_list, &buffer->entry);
  66. listSET_LIST_ITEM_OWNER(&buffer->entry, buffer);
  67. buffer++;
  68. }
  69. }
  70. static int h264_frame_buf_init(void)
  71. {
  72. h264_buf = pvPortMalloc(H264_FRAME_FIFO_COUNT * H264_FRAME_BUF_SIZE );
  73. if (h264_buf == NULL) {
  74. printf("malloc jpeg buf failed\r\n");
  75. return -1;
  76. }
  77. h264_frame_list_reset();
  78. return 0;
  79. }
  80. void h264_dec_ctx_init()
  81. {
  82. g_video_start = 0;
  83. xQueueSend(h264_frame_queue, NULL, 0);
  84. }
  85. void set_carlink_display_state(int on)
  86. {
  87. g_hide_carlink_flag = on;
  88. xQueueSend(h264_frame_queue, NULL, 0);
  89. }
  90. void set_carlink_display_state_irq(int on)
  91. {
  92. g_hide_carlink_flag = on;
  93. xQueueSendFromISR(h264_frame_queue, NULL, 0);
  94. }
  95. video_frame_s* get_h264_frame_buf()
  96. {
  97. video_frame_s* frame = NULL;
  98. ListItem_t* item = NULL;
  99. xSemaphoreTake(frame_list_mutex, portMAX_DELAY);
  100. if (g_video_start && !listLIST_IS_EMPTY(&frame_free_list)) {
  101. frame = list_first_entry(&frame_free_list);
  102. item = listGET_HEAD_ENTRY(&frame_free_list);
  103. uxListRemove(item);
  104. }
  105. xSemaphoreGive(frame_list_mutex);
  106. return frame;
  107. }
  108. void notify_h264_frame_ready(video_frame_s** frame)
  109. {
  110. //ListItem_t* item = NULL;
  111. video_frame_s * tmp = *frame;
  112. xSemaphoreTake(frame_list_mutex, portMAX_DELAY);
  113. if (NULL != tmp) {
  114. vListInsertEnd(&frame_ready_list, &tmp->entry);
  115. }
  116. xSemaphoreGive(frame_list_mutex);
  117. xQueueSend(h264_frame_queue, NULL, 0);
  118. }
  119. void set_h264_frame_free(video_frame_s* frame)
  120. {
  121. xSemaphoreTake(frame_list_mutex, portMAX_DELAY);
  122. if (g_video_start) {
  123. frame->cur = frame->buf;
  124. frame->len = 0;
  125. vListInsertEnd(&frame_free_list, &frame->entry);
  126. }
  127. xSemaphoreGive(frame_list_mutex);
  128. }
  129. static void h264_decode_proc(void *pvParameters)
  130. {
  131. MFCHandle *handle = NULL;
  132. DWLLinearMem_t inBuf;
  133. OutFrameBuffer outBuf = {0};
  134. int ret = -1, i;
  135. uint32_t align_width, align_height;
  136. uint32_t yaddr, uaddr, vaddr, dstaddr;
  137. video_frame_s* frame = NULL;
  138. uint32_t ts = get_timer(0), show_ts = 0, video_ts = 0;
  139. int32_t delta_ts = 0;;
  140. int carlink_lcd_take = 0;
  141. ListItem_t* item = NULL;
  142. //FF_FILE *fp = ff_fopen("/usb/ey.h264", "w+");
  143. handle = mfc_init(RAW_STRM_TYPE_H264_NOREORDER);
  144. if(!handle) {
  145. printf("%s, mfc_init failed.\r\n", __func__);
  146. goto exit;
  147. }
  148. g_video_start = 1;
  149. while(1) {
  150. if (xQueueReceive(h264_frame_queue, NULL, portMAX_DELAY) != pdPASS) {
  151. printf("%s xQueueReceive err!\r\n", __func__);
  152. continue;
  153. }
  154. if (g_video_start == 0) {
  155. printf("dec uninit\r\n");
  156. if (carlink_lcd_take) {
  157. ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0);
  158. ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
  159. vVideoDisplayBufGive();
  160. ark_lcd_osd_enable(LCD_UI_LAYER, 1);
  161. ark_lcd_set_osd_sync(LCD_UI_LAYER);
  162. carlink_lcd_take = 0;
  163. }
  164. mfc_uninit(handle);
  165. xSemaphoreTake(frame_list_mutex, portMAX_DELAY);
  166. h264_frame_list_reset();
  167. xSemaphoreGive(frame_list_mutex);
  168. xQueueReset(h264_frame_queue);
  169. handle = mfc_init(RAW_STRM_TYPE_H264_NOREORDER);
  170. if(!handle) {
  171. printf("%s, mfc_reinit failed.\r\n", __func__);
  172. continue;
  173. }
  174. g_video_start = 1;
  175. continue;
  176. }
  177. if (g_hide_carlink_flag == 0) {
  178. ark_lcd_osd_enable(LCD_VIDEO_LAYER, 0);
  179. ark_lcd_osd_enable(LCD_UI_LAYER, 1);
  180. ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
  181. ark_lcd_set_osd_sync(LCD_UI_LAYER);
  182. }
  183. xSemaphoreTake(frame_list_mutex, portMAX_DELAY);
  184. if (!listLIST_IS_EMPTY(&frame_ready_list)) {
  185. frame = list_first_entry(&frame_ready_list);
  186. item = listGET_HEAD_ENTRY(&frame_ready_list);
  187. uxListRemove(item);
  188. } else {
  189. xSemaphoreGive(frame_list_mutex);
  190. continue;
  191. }
  192. xSemaphoreGive(frame_list_mutex);
  193. memset(&outBuf, 0, sizeof(OutFrameBuffer));
  194. inBuf.busAddress = (u32)frame->cur;
  195. inBuf.virtualAddress = (u32 *)inBuf.busAddress;
  196. inBuf.size = frame->len;
  197. CP15_clean_dcache_for_dma(inBuf.busAddress, inBuf.busAddress + inBuf.size);
  198. ts = get_timer(0);
  199. //printf("start dec...\r\n");
  200. ret = mfc_decode(handle, &inBuf, &outBuf);
  201. //ret = 0;
  202. //if (NULL != fp)
  203. // ret = ff_fwrite((void*)inBuf.virtualAddress, 1, inBuf.size, fp);
  204. xSemaphoreTake(frame_list_mutex, portMAX_DELAY);
  205. frame->cur = frame->buf;
  206. frame->len = 0;
  207. vListInsertEnd(&frame_free_list, &frame->entry);
  208. xSemaphoreGive(frame_list_mutex);
  209. if (ret < 0) {
  210. printf("h264 decode fail.\n");
  211. continue;
  212. }//printf("dec num:%d use:%d ms\r\n", outBuf.num, (get_timer(0) - ts) / 1000);
  213. //continue;
  214. for(i = 0; i < outBuf.num; i++) {
  215. align_width = outBuf.frameWidth;
  216. align_height = outBuf.frameHeight;
  217. if(!(align_width && align_height))
  218. continue;
  219. yaddr = outBuf.buffer[i].yBusAddress;
  220. uaddr = yaddr + align_width * align_height;
  221. vaddr = yaddr + align_width * align_height * 5/4;
  222. if (carlink_lcd_take == 0) {
  223. carlink_lcd_take = 1;
  224. xVideoDisplayBufTake(portMAX_DELAY);
  225. }
  226. if (carlink_lcd_take) {
  227. LcdOsdInfo info = {0};
  228. if (0 == g_hide_carlink_flag)
  229. continue;
  230. show_ts = get_timer(0);
  231. info.format = LCD_OSD_FORAMT_Y_UV420; //set default format.
  232. if ((info.format == LCD_OSD_FORAMT_RGB565) || \
  233. (g_disp_width != g_video_width) || (g_disp_height != g_video_height)) {
  234. uint32_t pxp_width, pxp_height;
  235. int pxp_out_fmt = PXP_OUT_FORMAT_YUV2P420;
  236. if(info.format == LCD_OSD_FORAMT_RGB565)
  237. pxp_out_fmt = PXP_OUT_FORMAT_RGB565;
  238. //align_width = ((outBuf.frameWidth + 0xf) & (~0xf));
  239. if (outBuf.frameWidth != g_video_width)
  240. align_width = g_video_width;
  241. else
  242. align_width = outBuf.frameWidth ;
  243. if (outBuf.frameHeight != g_video_height)
  244. align_height = g_video_height;
  245. else
  246. align_height = outBuf.frameHeight;
  247. pxp_width = g_disp_width;
  248. pxp_height = g_disp_height;
  249. dstaddr = ulVideoDisplayBufGet();
  250. pxp_scaler_rotate(yaddr, uaddr, vaddr, PXP_S0_FORMAT_YUV2P420, align_width, align_height,
  251. dstaddr, dstaddr + pxp_width * pxp_height, pxp_out_fmt, pxp_width, pxp_height, LCD_ROTATE_ANGLE);
  252. info.yaddr = dstaddr;
  253. info.uaddr = dstaddr + pxp_width * pxp_height;
  254. info.vaddr = 0;
  255. } else {
  256. info.yaddr = yaddr;
  257. info.uaddr = uaddr;
  258. info.vaddr = vaddr;
  259. }
  260. info.x = g_disp_x;
  261. info.y = g_disp_y;
  262. info.width = g_disp_width;
  263. info.height = g_disp_height;
  264. if (!ark_lcd_get_osd_info_atomic_isactive(LCD_VIDEO_LAYER)) {
  265. ark_lcd_wait_for_vsync();
  266. }
  267. ark_lcd_set_osd_info_atomic(LCD_VIDEO_LAYER, &info);
  268. ark_lcd_osd_enable(LCD_VIDEO_LAYER, 1);
  269. ark_lcd_set_osd_sync(LCD_VIDEO_LAYER);
  270. ark_lcd_osd_enable(LCD_UI_LAYER, 0);
  271. ark_lcd_set_osd_sync(LCD_UI_LAYER);
  272. vVideoDisplayBufRender(dstaddr);
  273. if (outBuf.num > 1) {// for apple h264
  274. video_ts = (1000 / g_video_fps);
  275. show_ts = (get_timer(0) - show_ts) / 1000;
  276. delta_ts = ((int32_t)video_ts - (int32_t)show_ts) -3;
  277. //printf("delay %d ms\r\n", delta_ts);
  278. if (delta_ts > 0)
  279. vTaskDelay(pdMS_TO_TICKS(delta_ts));
  280. }
  281. }
  282. }
  283. //printf("all use:%d ms dec:%ld ms all ts:%ld ms\r\n", (get_timer(0) - ts) / 1000, dec_ts, (get_timer(0) - all_ts) / 1000);
  284. //all_ts = get_timer(0);
  285. }
  286. exit:
  287. if (NULL != handle)
  288. mfc_uninit(handle);
  289. vTaskDelete(NULL);
  290. }
  291. int carlink_ey_video_init()
  292. {
  293. int ret = -1;
  294. if (g_init_flag ==1) {
  295. return 0;
  296. }
  297. g_init_flag = 1;
  298. ret = h264_frame_buf_init();
  299. frame_list_mutex = xSemaphoreCreateMutex();
  300. //h264_frame_queue = xQueueCreate(H264_FRAME_FIFO_COUNT, sizeof(uint32_t));
  301. h264_frame_queue = xQueueCreate(1, 0);
  302. ret = xTaskCreate(h264_decode_proc, "h264_decode_proc", 2048 * 4, NULL, configMAX_PRIORITIES - 3, &dec_h264_handle);
  303. return ret;
  304. }