Codec.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471
  1. //
  2. // Created by root on 17-11-1.
  3. //
  4. #include "Codec.h"
  5. #define cxx_log(fmt,...)\
  6. do {\
  7. printf(fmt,##__VA_ARGS__);\
  8. } while(0)
  9. using namespace std;
  10. Codec::Codec() : mFps(0),
  11. mEos(0),
  12. mID(0),
  13. mDisPlay(0),
  14. mFrmCnt(0),
  15. mFrmRate(0.0),
  16. mFin(NULL),
  17. mFout(NULL),
  18. mPktBuf(NULL),
  19. mCtx(NULL),
  20. mApi(NULL),
  21. mPkt(NULL),
  22. mFrmGrp(NULL)
  23. {
  24. }
  25. Codec::~Codec() {
  26. if (mPkt) {
  27. mpp_packet_deinit(&mPkt);
  28. mPkt = NULL;
  29. }
  30. if (mCtx) {
  31. mpp_destroy(mCtx);
  32. mCtx = NULL;
  33. }
  34. if (mPktBuf) {
  35. delete(mPktBuf);
  36. mPktBuf = NULL;
  37. }
  38. if (mBuffer) {
  39. mpp_buffer_put(mBuffer);
  40. mBuffer = NULL;
  41. }
  42. if (mFrmGrp) {
  43. mpp_buffer_group_put(mFrmGrp);
  44. mFrmGrp = NULL;
  45. }
  46. if (mFin) {
  47. fclose(mFin);
  48. mFin = NULL;
  49. }
  50. if (mFout) {
  51. fclose(mFout);
  52. mFout = NULL;
  53. }
  54. if (mRGA) {
  55. delete(mRGA);
  56. mRGA = NULL;
  57. }
  58. }
  59. int Codec::init(const char *file_input,
  60. const char *file_output, MppCodingType type,
  61. int src_w, int src_h, int display) {
  62. int ret = 0;
  63. int x, y, i;
  64. RK_U32 need_split = 1;
  65. MpiCmd mpi_cmd = MPP_CMD_BASE;
  66. MppParam param = NULL;
  67. mDisPlay = display;
  68. srcW = src_w;
  69. srcH = src_h;
  70. dstW = src_w;
  71. dstH = src_h;
  72. mFin = fopen(file_input, "rb");
  73. if (!mFin) {
  74. cxx_log("failed to open input file %s.\n", file_input);
  75. return -1;
  76. }
  77. mFout = fopen(file_output, "wb+");
  78. if (!mFout) {
  79. cxx_log("failed to open output file %s.\n", file_output);
  80. return -2;
  81. }
  82. mPktBuf = new char[PKT_SIZE];
  83. if (!mPktBuf) {
  84. cxx_log("failed to malloc mPktBuf.\n");
  85. return -3;
  86. }
  87. ret = mpp_packet_init(&mPkt, mPktBuf, PKT_SIZE);
  88. if (ret) {
  89. cxx_log("failed to exec mpp_packet_init ret %d", ret);
  90. return -4;
  91. }
  92. ret = mpp_create(&mCtx, &mApi);
  93. if (ret != MPP_OK) {
  94. cxx_log("failed to exec mpp_create ret %d", ret);
  95. return -5;
  96. }
  97. mpi_cmd = MPP_DEC_SET_PARSER_SPLIT_MODE;
  98. param = &need_split;
  99. ret = mApi->control(mCtx, mpi_cmd, param);
  100. if (ret != MPP_OK) {
  101. cxx_log("failed to control MPP_DEC_SET_PARSER_SPLIT_MODE.\n");
  102. return -6;
  103. }
  104. ret = mpp_init(mCtx, MPP_CTX_DEC, type);
  105. if (ret != MPP_OK) {
  106. cxx_log("failed to exec mpp_init.\n");
  107. return -7;
  108. }
  109. mRGA = new RGA();
  110. ret = mRGA->init(srcW, srcH, srcW, srcH);
  111. if (ret < 0) {
  112. cxx_log("failed to exec mRGA->init %d.\n", ret);
  113. return -8;
  114. }
  115. mDev = create_sp_dev();
  116. if (!mDev) {
  117. cxx_log("failed to exec create_sp_dev.\n");
  118. return -10;
  119. }
  120. ret = initialize_screens(mDev);
  121. if (ret != 0) {
  122. cxx_log("failed to exec initialize_screens.\n");
  123. return -11;
  124. }
  125. mPlanes = (sp_plane **)calloc(mDev->num_planes, sizeof(*mPlanes));
  126. if (!mPlanes) {
  127. cxx_log("failed to calloc mPlanes.\n");
  128. return -12;
  129. }
  130. mCrtc = &mDev->crtcs[0];
  131. for (i = 0; i < mCrtc->num_planes; i++) {
  132. mPlanes[i] = get_sp_plane(mDev, mCrtc);
  133. if (is_supported_format(mPlanes[i], DRM_FORMAT_NV12))
  134. mTestPlane = mPlanes[i];
  135. }
  136. if (!mTestPlane) {
  137. cxx_log("failed to get mTestPlane.\n");
  138. return -13;
  139. }
  140. return 0;
  141. }
  142. static RK_S64 get_time() {
  143. struct timeval tv_date;
  144. gettimeofday(&tv_date, NULL);
  145. return (RK_S64)tv_date.tv_sec * 1000000 + (RK_S64)tv_date.tv_usec;
  146. }
  147. int Codec::dump_mpp_frame_to_file(MppFrame frame, FILE *fp)
  148. {
  149. RK_U32 width = 0;
  150. RK_U32 height = 0;
  151. RK_U32 h_stride = 0;
  152. RK_U32 v_stride = 0;
  153. MppFrameFormat fmt = MPP_FMT_YUV420SP;
  154. MppBuffer buffer = NULL;
  155. RK_U8 *base = NULL;
  156. if (!fp || !frame)
  157. return -1;
  158. width = mpp_frame_get_width(frame);
  159. height = mpp_frame_get_height(frame);
  160. h_stride = mpp_frame_get_hor_stride(frame);
  161. v_stride = mpp_frame_get_ver_stride(frame);
  162. fmt = mpp_frame_get_fmt(frame);
  163. buffer = mpp_frame_get_buffer(frame);
  164. if(!buffer)
  165. return -2;
  166. base = (RK_U8 *)mpp_buffer_get_ptr(buffer);
  167. {
  168. RK_U32 i;
  169. RK_U8 *base_y = base;
  170. RK_U8 *base_u = base + h_stride * v_stride;
  171. RK_U8 *base_v = base_u + h_stride * v_stride / 4;
  172. for (i = 0; i < height; i++, base_y += h_stride)
  173. fwrite(base_y, 1, width, fp);
  174. for (i = 0; i < height / 2; i++, base_u += h_stride / 2)
  175. fwrite(base_u, 1, width / 2, fp);
  176. for (i = 0; i < height / 2; i++, base_v += h_stride / 2)
  177. fwrite(base_v, 1, width / 2, fp);
  178. }
  179. return 0;
  180. }
  181. int Codec::drm_show_frmae(MppFrame frame) {
  182. sp_bo *bo;
  183. uint32_t handles[4], pitches[4], offsets[4];
  184. int width, height;
  185. int frm_size, ret, fd, err;
  186. err = mpp_frame_get_errinfo(frame) |
  187. mpp_frame_get_discard(frame);
  188. if (err) {
  189. cxx_log("get err info %d discard %d,go back.\n",
  190. mpp_frame_get_errinfo(frame),
  191. mpp_frame_get_discard(frame));
  192. return -1;
  193. }
  194. width = mpp_frame_get_width(frame);
  195. height = mpp_frame_get_height(frame);
  196. width = CODEC_ALIGN(width, 16);
  197. height = CODEC_ALIGN(height, 16);
  198. frm_size = width * height * 3 / 2;
  199. fd = mpp_buffer_get_fd(mpp_frame_get_buffer(frame));
  200. bo = (struct sp_bo *)calloc(1, sizeof(struct sp_bo));
  201. if (!bo) {
  202. cxx_log("failed to calloc bo.\n");
  203. return -2;
  204. }
  205. drmPrimeFDToHandle(mDev->fd, fd, &bo->handle);
  206. bo->dev = mDev;
  207. bo->width = width;
  208. bo->height = height;
  209. bo->depth = 16;
  210. bo->bpp = 32;
  211. bo->format = DRM_FORMAT_NV12;
  212. bo->flags = 0;
  213. handles[0] = bo->handle;
  214. pitches[0] = width;
  215. offsets[0] = 0;
  216. handles[1] = bo->handle;
  217. pitches[1] = width;
  218. offsets[1] = width * height;
  219. ret = drmModeAddFB2(mDev->fd, bo->width, bo->height,
  220. bo->format, handles, pitches, offsets,
  221. &bo->fb_id, bo->flags);
  222. if (ret != 0) {
  223. cxx_log("failed to exec drmModeAddFb2.\n");
  224. return -3;
  225. }
  226. ret = drmModeSetPlane(mDev->fd, mTestPlane->plane->plane_id,
  227. mCrtc->crtc->crtc_id, bo->fb_id, 0, 0, 0,
  228. mCrtc->crtc->mode.hdisplay,
  229. mCrtc->crtc->mode.vdisplay,
  230. 0, 0, bo->width << 16, bo->height << 16);
  231. if (ret) {
  232. cxx_log("failed to exec drmModeSetPlane.\n");
  233. return -3;
  234. }
  235. if (mTestPlane->bo) {
  236. if (mTestPlane->bo->fb_id) {
  237. ret = drmModeRmFB(mDev->fd, mTestPlane->bo->fb_id);
  238. if (ret)
  239. cxx_log("failed to exec drmModeRmFB.\n");
  240. }
  241. if (mTestPlane->bo->handle) {
  242. struct drm_gem_close req = {
  243. .handle = mTestPlane->bo->handle,
  244. };
  245. drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
  246. }
  247. free(mTestPlane->bo);
  248. }
  249. mTestPlane->bo = bo;
  250. return 0;
  251. }
  252. int Codec::decode_one_pkt(char *buf, int size, MppFrame *srcFrm, MppFrame *dstFrm) {
  253. int ret = 0;
  254. RK_U32 pkt_done = 0;
  255. mpp_packet_write(mPkt, 0, buf, size);
  256. mpp_packet_set_pos(mPkt, buf);
  257. mpp_packet_set_length(mPkt, size);
  258. if (mEos)
  259. mpp_packet_set_eos(mPkt);
  260. do {
  261. RK_S32 times = 5;
  262. if (!pkt_done) {
  263. ret = mApi->decode_put_packet(mCtx, mPkt);
  264. if (ret == MPP_OK)
  265. pkt_done = 1;
  266. }
  267. do {
  268. RK_S32 get_frm = 0;
  269. RK_U32 frm_eos = 0;
  270. try_again:
  271. ret = mApi->decode_get_frame(mCtx, srcFrm);
  272. if (ret == MPP_ERR_TIMEOUT) {
  273. if (times > 0) {
  274. times--;
  275. usleep(2000);
  276. goto try_again;
  277. }
  278. cxx_log("decode_get_frame failed too much time.\n");
  279. }
  280. if (ret != MPP_OK) {
  281. cxx_log("decode_get_frame failed ret %d.\n", ret);
  282. break;
  283. }
  284. if (*srcFrm) {
  285. if (mpp_frame_get_info_change(*srcFrm)) {
  286. RK_U32 width = mpp_frame_get_width(*srcFrm);
  287. RK_U32 height = mpp_frame_get_height(*srcFrm);
  288. RK_U32 hor_stride = mpp_frame_get_hor_stride(*srcFrm);
  289. RK_U32 ver_stride = mpp_frame_get_ver_stride(*srcFrm);
  290. cxx_log("decode_get_frame get info changed found.\n");
  291. cxx_log("decoder require buffer w:h [%d:%d] stride [%d:%d]",
  292. width, height, hor_stride, ver_stride);
  293. ret = mpp_buffer_group_get_internal(&mFrmGrp, MPP_BUFFER_TYPE_DRM);
  294. if (ret) {
  295. cxx_log("get mpp buffer group failed ret %d.\n", ret);
  296. break;
  297. }
  298. mApi->control(mCtx, MPP_DEC_SET_EXT_BUF_GROUP, mFrmGrp);
  299. mApi->control(mCtx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
  300. } else {
  301. cxx_log("decode_get_frame ID:%d get srcFrm %d.\n", mID, mFrmCnt++);
  302. if (mDisPlay) {
  303. ret = mRGA->swscale(mpp_buffer_get_fd(mpp_frame_get_buffer(*srcFrm)),
  304. mpp_buffer_get_fd(mpp_frame_get_buffer(*dstFrm)));
  305. if (ret < 0) {
  306. cxx_log("failed to exec mRGA->swscale ret:%d.\n", ret);
  307. } else {
  308. drm_show_frmae(*dstFrm);
  309. if (mFout) {
  310. /*
  311. * note that write file will leads to IO block
  312. * so if you want to test frame rate,don't wirte
  313. * it.
  314. */
  315. //dump_mpp_frame_to_file(*srcFrm, mFout);
  316. }
  317. }
  318. }
  319. }
  320. frm_eos = mpp_frame_get_eos(*srcFrm);
  321. mpp_frame_deinit(srcFrm);
  322. *srcFrm = NULL;
  323. get_frm = 1;
  324. }
  325. if (mEos && pkt_done && !frm_eos) {
  326. usleep(10000);
  327. continue;
  328. }
  329. if (frm_eos) {
  330. cxx_log("found last frame.\n");
  331. break;
  332. }
  333. if (get_frm)
  334. continue;
  335. break;
  336. } while (1);
  337. if (pkt_done)
  338. break;
  339. /*
  340. * why sleep here?
  341. * mpp has a internal input pakcet list,if it is full, wait here 3ms to
  342. * wait internal list isn't full.
  343. */
  344. usleep(3000);
  345. } while (1);
  346. return 0;
  347. }
  348. int Codec::decode() {
  349. MppFrame srcFrm;
  350. MppFrame dstFrm;
  351. double timeDiff;
  352. int ret = 0;
  353. int hor_stride = CODEC_ALIGN(dstW, 16);
  354. int ver_srride = CODEC_ALIGN(dstH, 16);
  355. ret = mpp_frame_init(&dstFrm);
  356. if (ret) {
  357. cxx_log("failed to exec mpp_frame_init %d.\n", ret);
  358. return -1;
  359. }
  360. mpp_buffer_get(mFrmGrp, &mBuffer, hor_stride * ver_srride * 3 / 2);
  361. mpp_frame_set_width(dstFrm, dstW);
  362. mpp_frame_set_height(dstFrm, dstH);
  363. mpp_frame_set_hor_stride(dstFrm, hor_stride);
  364. mpp_frame_set_ver_stride(dstFrm, ver_srride);
  365. mpp_frame_set_fmt(dstFrm, MPP_FMT_YUV420P);
  366. mpp_frame_set_buffer(dstFrm, mBuffer);
  367. mTimeS = get_time();
  368. while (!mEos) {
  369. size_t read_size = fread(mPktBuf, 1, PKT_SIZE, mFin);
  370. if (read_size != PKT_SIZE || feof(mFin)) {
  371. cxx_log("found last packet.\n");
  372. mEos = 1;
  373. }
  374. mpp_frame_set_eos(dstFrm, mEos);
  375. ret = decode_one_pkt(mPktBuf, read_size, &srcFrm, &dstFrm);
  376. if (ret < 0) {
  377. cxx_log("failed to exec decode.\n");
  378. return -2;
  379. }
  380. }
  381. mpp_frame_deinit(&dstFrm);
  382. mTimeE = get_time();
  383. timeDiff = double(mTimeE - mTimeS)/1000;
  384. mFrmRate = (mFrmCnt * 1000) / timeDiff;
  385. cxx_log("decode frames %d using %.2fms frm rate:%.2f.\n", mFrmCnt,
  386. timeDiff, mFrmRate);
  387. return 0;
  388. }
  389. int Codec::deinit() {
  390. int ret = 0;
  391. ret = mApi->reset(mCtx);
  392. if (ret != MPP_OK) {
  393. cxx_log("failed to exec mApi->reset.\n");
  394. return -1;
  395. }
  396. }