td_h264enc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. /*
  2. * Copyright (C) 2009-2010 Felipe Contreras
  3. * Copyright (C) 2009-2010 Nokia Corporation
  4. *
  5. * Authors:
  6. * Felipe Contreras <felipe.contreras@gmail.com>
  7. * Juha Alanen <juha.m.alanen@nokia.com>
  8. *
  9. * This file may be used under the terms of the GNU Lesser General Public
  10. * License version 2.1, a copy of which is found in LICENSE included in the
  11. * packaging of this file.
  12. */
  13. #include "dsp_bridge.h"
  14. #include "dmm_buffer.h"
  15. #include "gstdspbase.h"
  16. #include "gstdspvenc.h"
  17. struct create_args {
  18. uint32_t size;
  19. uint16_t num_streams;
  20. uint16_t in_id;
  21. uint16_t in_type;
  22. uint16_t in_count;
  23. uint16_t out_id;
  24. uint16_t out_type;
  25. uint16_t out_count;
  26. uint16_t reserved;
  27. uint32_t width;
  28. uint32_t height;
  29. uint32_t max_bitrate;
  30. uint32_t bitstream_buf_size;
  31. uint32_t intra_frame_period;
  32. uint32_t framerate;
  33. uint8_t yuv_format;
  34. uint8_t unrestricted_mv; /* not supported */
  35. uint8_t num_ref_frames; /* not supported */
  36. uint8_t rc_algorithm;
  37. uint8_t idr_enable; /* not used */
  38. uint8_t deblocking_enable;
  39. uint8_t mv_range;
  40. uint8_t qpi_frame;
  41. uint8_t profile;
  42. uint8_t level;
  43. uint16_t nal_mode;
  44. uint32_t encoding_preset;
  45. uint32_t rc_algo;
  46. };
  47. static void create_args(GstDspBase *base, unsigned *profile_id, void **arg_data)
  48. {
  49. GstDspVEnc *self = GST_DSP_VENC(base);
  50. struct create_args args = {
  51. .size = sizeof(args) - 4,
  52. .num_streams = 2,
  53. .in_id = 0,
  54. .in_type = 0,
  55. .in_count = base->ports[0]->num_buffers,
  56. .out_id = 1,
  57. .out_type = 0,
  58. .out_count = base->ports[1]->num_buffers,
  59. .width = self->width,
  60. .height = self->height,
  61. .max_bitrate = self->max_bitrate,
  62. .bitstream_buf_size = base->output_buffer_size,
  63. .intra_frame_period = self->framerate,
  64. .framerate = self->framerate * 1000,
  65. .yuv_format = (self->color_format == GST_MAKE_FOURCC('U','Y','V','Y') ? 2 : 0),
  66. .num_ref_frames = 1, /* not supported */
  67. .rc_algorithm = 1, /* 0 = var, 1 == constant, 2 == none */
  68. .deblocking_enable = 1,
  69. .mv_range = 64,
  70. .qpi_frame = 28,
  71. .profile = 66, /* Baseline profile */
  72. .level = self->level,
  73. #ifdef MAEMO_5
  74. .nal_mode = self->priv.h264.bytestream ? 0 : 1, /* 0 == bytestream, 1 == NALU, 2 == bytestream, with NALU sizes */
  75. #else
  76. .nal_mode = self->priv.h264.bytestream ? 2 : 1, /* 0 == bytestream, 1 == NALU, 2 == bytestream, with NALU sizes */
  77. #endif
  78. .encoding_preset = 3,
  79. };
  80. if (self->mode == 0)
  81. args.rc_algorithm = 0; /* storage VBR */
  82. else
  83. args.rc_algorithm = 1; /* low delay CBR */
  84. if (self->width * self->height > 352 * 288)
  85. *profile_id = 2;
  86. else if (self->width * self->height > 176 * 144)
  87. *profile_id = 1;
  88. else
  89. *profile_id = 0;
  90. *arg_data = malloc(sizeof(args));
  91. memcpy(*arg_data, &args, sizeof(args));
  92. }
  93. struct in_params {
  94. uint32_t params_size;
  95. uint32_t input_height;
  96. uint32_t input_width;
  97. uint32_t ref_framerate;
  98. uint32_t framerate;
  99. uint32_t bitrate;
  100. uint32_t intra_frame_interval;
  101. uint32_t generate_header;
  102. uint32_t capture_width;
  103. uint32_t force_i_frame;
  104. uint32_t qp_intra;
  105. uint32_t qp_inter;
  106. uint32_t qp_max;
  107. uint32_t qp_min;
  108. uint32_t lf_disable_idc;
  109. uint32_t quarter_pel_disable;
  110. uint32_t air_mb_period;
  111. uint32_t max_mbs_per_slice;
  112. uint32_t max_bytes_per_slice;
  113. uint32_t slice_refresh_row_start_number;
  114. uint32_t slice_refresh_row_number;
  115. uint32_t filter_offset_a;
  116. uint32_t filter_offset_b;
  117. uint32_t log2MaxFNumMinus4;
  118. uint32_t chroma_qpi_index_offset;
  119. uint32_t constrained_intra_pred_enable;
  120. uint32_t pic_order_count_type;
  121. uint32_t max_mv_per_mb;
  122. uint32_t intra_4x4_enable_idc;
  123. uint32_t mv_data_enable;
  124. uint32_t hier_coding_enable;
  125. uint32_t stream_format;
  126. uint32_t intra_refresh_method;
  127. uint32_t perceptual_quant;
  128. uint32_t scene_change_det;
  129. void (*nal_callback_func)(uint32_t *buf, uint32_t *buf_size, void *context);
  130. void *context;
  131. uint32_t num_slice_aso;
  132. uint32_t aso_slice_order[8]; /* MAXNUMSLCGPS = 8 */
  133. uint32_t num_slice_groups;
  134. uint32_t slice_group_map_type;
  135. uint32_t slice_group_change_direction_flag;
  136. uint32_t slice_group_change_rate;
  137. uint32_t slice_group_change_cycle;
  138. uint32_t slice_group_params[8]; /* MAXNUMSLCGPS = 8 */
  139. uint32_t max_delay;
  140. uint32_t frame_index;
  141. };
  142. struct out_params {
  143. union {
  144. struct {
  145. uint32_t bitstream_size;
  146. int32_t frame_type;
  147. uint32_t nalus_per_frame;
  148. uint32_t nalu_sizes[1618];
  149. uint32_t frame_index; /* Gives the number of the input frame which NAL unit belongs */
  150. uint32_t nalu_index; /* Number of current NAL unit inside the frame */
  151. }v0;
  152. struct {
  153. uint32_t bitstream_size;
  154. int32_t frame_type;
  155. uint32_t nalus_per_frame;
  156. uint32_t nalu_sizes[240];
  157. uint32_t frame_index; /* Gives the number of the input frame which NAL unit belongs */
  158. uint32_t nalu_index; /* Number of current NAL unit inside the frame */
  159. int32_t error_code;
  160. }v1;
  161. } ver;
  162. };
  163. #define OUT_PARAMS_VER(base, out_params, value) \
  164. (*(base->sn_api?&(out_params->ver.v1.value):&(out_params->ver.v0.value)))
  165. #define OUT_PARAMS_SIZE_VER(base, out_params) \
  166. (base->sn_api?sizeof(out_params->ver.v1):sizeof(out_params->ver.v0))
  167. static void in_send_cb(GstDspBase *base, struct td_buffer *tb)
  168. {
  169. struct in_params *param;
  170. GstDspVEnc *self = GST_DSP_VENC(base);
  171. param = tb->params->data;
  172. param->frame_index = g_atomic_int_exchange_and_add(&self->frame_index, 1);
  173. param->bitrate = g_atomic_int_get(&self->bitrate);
  174. g_mutex_lock(self->keyframe_mutex);
  175. param->force_i_frame = self->keyframe_event ? 1 : 0;
  176. if (self->keyframe_event) {
  177. gst_pad_push_event(base->srcpad, self->keyframe_event);
  178. self->keyframe_event = NULL;
  179. }
  180. g_mutex_unlock(self->keyframe_mutex);
  181. }
  182. static void create_codec_data(GstDspBase *base)
  183. {
  184. GstDspVEnc *self = GST_DSP_VENC(base);
  185. guint8 *sps, *pps, *codec_data;
  186. guint16 sps_size, pps_size, offset;
  187. sps = GST_BUFFER_DATA(self->priv.h264.sps);
  188. pps = GST_BUFFER_DATA(self->priv.h264.pps);
  189. sps_size = GST_BUFFER_SIZE(self->priv.h264.sps);
  190. pps_size = GST_BUFFER_SIZE(self->priv.h264.pps);
  191. offset = 0;
  192. self->priv.h264.codec_data = gst_buffer_new_and_alloc(sps_size + pps_size + 11);
  193. codec_data = GST_BUFFER_DATA(self->priv.h264.codec_data);
  194. codec_data[offset++] = 0x01;
  195. codec_data[offset++] = sps[1]; /* AVCProfileIndication*/
  196. codec_data[offset++] = sps[2]; /* profile_compatibility*/
  197. codec_data[offset++] = sps[3]; /* AVCLevelIndication */
  198. codec_data[offset++] = 0xff;
  199. codec_data[offset++] = 0xe1;
  200. codec_data[offset++] = (sps_size >> 8) & 0xff;
  201. codec_data[offset++] = sps_size & 0xff;
  202. memcpy(codec_data + offset, sps, sps_size);
  203. offset += sps_size;
  204. codec_data[offset++] = 0x1;
  205. codec_data[offset++] = (pps_size >> 8) & 0xff;
  206. codec_data[offset++] = pps_size & 0xff;
  207. memcpy(codec_data + offset, pps, pps_size);
  208. }
  209. static void strip_sps_pps_header(GstDspBase *base,
  210. dmm_buffer_t *b,
  211. struct out_params *param)
  212. {
  213. GstDspVEnc *self = GST_DSP_VENC(base);
  214. char *data = b->data;
  215. unsigned i;
  216. if (OUT_PARAMS_VER(base,param,nalus_per_frame) <= 1)
  217. return;
  218. if (!self->priv.h264.sps_received) {
  219. self->priv.h264.sps_received = TRUE;
  220. return;
  221. }
  222. for (i = 0; i < OUT_PARAMS_VER(base,param,nalus_per_frame); i++) {
  223. if ((data[4] & 0x1f) == 7 || (data[4] & 0x1f) == 8) {
  224. data += OUT_PARAMS_VER(base,param,nalu_sizes[i]);
  225. b->data = data;
  226. b->len -= OUT_PARAMS_VER(base,param,nalu_sizes[i]);
  227. }
  228. }
  229. }
  230. static void ignore_sps_pps_header(GstDspBase *base, dmm_buffer_t *b)
  231. {
  232. char *data = b->data;
  233. if ((data[4] & 0x1f) == 7 || (data[4] & 0x1f) == 8)
  234. base->skip_hack_2++;
  235. }
  236. static void out_recv_cb(GstDspBase *base, struct td_buffer *tb)
  237. {
  238. GstDspVEnc *self = GST_DSP_VENC(base);
  239. dmm_buffer_t *b = tb->data;
  240. struct out_params *param;
  241. param = tb->params->data;
  242. pr_debug(base, "frame type: %d", OUT_PARAMS_VER(base, param,frame_type));
  243. tb->keyframe = (OUT_PARAMS_VER(base, param,frame_type) == 1 || OUT_PARAMS_VER(base, param,frame_type) == 4);
  244. if (b->len == 0)
  245. return;
  246. if (self->priv.h264.bytestream) {
  247. strip_sps_pps_header(base, b, param);
  248. return;
  249. }
  250. if (G_LIKELY(self->priv.h264.codec_data_done)) {
  251. /* prefix the NALU with a lenght field, not counting the start code */
  252. *(uint32_t*)b->data = GINT_TO_BE(b->len - 4);
  253. ignore_sps_pps_header(base, b);
  254. }
  255. else {
  256. if (!self->priv.h264.sps_received) {
  257. /* skip the start code 0x00000001 when storing SPS */
  258. self->priv.h264.sps = gst_buffer_new_and_alloc(b->len - 4);
  259. memcpy(GST_BUFFER_DATA(self->priv.h264.sps), b->data + 4, b->len - 4);
  260. self->priv.h264.sps_received = TRUE;
  261. } else if (!self->priv.h264.pps_received) {
  262. /* skip the start code 0x00000001 when storing PPS */
  263. self->priv.h264.pps = gst_buffer_new_and_alloc(b->len - 4);
  264. memcpy(GST_BUFFER_DATA(self->priv.h264.pps), b->data + 4, b->len - 4);
  265. self->priv.h264.pps_received = TRUE;
  266. }
  267. if (self->priv.h264.pps_received && self->priv.h264.sps_received) {
  268. create_codec_data(base);
  269. if (gstdsp_set_codec_data_caps(base, self->priv.h264.codec_data)) {
  270. self->priv.h264.codec_data_done = TRUE;
  271. gst_buffer_replace(&self->priv.h264.sps, NULL);
  272. gst_buffer_replace(&self->priv.h264.pps, NULL);
  273. gst_buffer_replace(&self->priv.h264.codec_data, NULL);
  274. }
  275. }
  276. base->skip_hack_2++;
  277. }
  278. }
  279. static void setup_in_params(GstDspBase *base, dmm_buffer_t *tmp)
  280. {
  281. struct in_params *in_param;
  282. GstDspVEnc *self = GST_DSP_VENC(base);
  283. int bits_per_mb;
  284. in_param = tmp->data;
  285. in_param->params_size = sizeof(*in_param);
  286. in_param->input_height = self->height;
  287. in_param->input_width = self->width;
  288. in_param->ref_framerate = self->framerate * 1000;
  289. in_param->framerate = self->framerate * 1000;
  290. in_param->bitrate = self->bitrate;
  291. in_param->intra_frame_interval = self->keyframe_interval * self->framerate;
  292. /* QP selection for the first frame */
  293. bits_per_mb = (in_param->bitrate / self->framerate) /
  294. (in_param->input_width * in_param->input_height / 256);
  295. if (bits_per_mb >= 50) {
  296. in_param->qp_intra = 0x1c;
  297. in_param->qp_inter = 0x1c;
  298. } else {
  299. in_param->qp_intra = 0x28;
  300. in_param->qp_inter = 0x28;
  301. }
  302. in_param->qp_max = 0x33;
  303. in_param->max_mbs_per_slice = 3620;
  304. in_param->max_bytes_per_slice = 327680;
  305. in_param->max_mv_per_mb = 4;
  306. in_param->intra_4x4_enable_idc = 2;
  307. if (self->mode == 1) {
  308. /* Max delay in CBR, unit is 1/30th of a second */
  309. in_param->max_delay = 6; /* 200ms */
  310. }
  311. if (self->intra_refresh) {
  312. unsigned pixels;
  313. /* For refreshing all the macroblocks in 3 sec */
  314. in_param->air_mb_period = self->framerate * 3;
  315. /* At least two intra macroblocks per frame */
  316. pixels = self->width * self->height;
  317. if (in_param->air_mb_period > pixels / (256 * 2))
  318. in_param->air_mb_period = pixels / (256 * 2);
  319. /*
  320. * Intra refresh methods:
  321. * 0 Doesn't insert forcefully intra macro blocks
  322. * 1 Inserts intra macro blocks in a cyclic fashion :
  323. * cyclic interval is equal to airMbPeriod
  324. * 3 Position of intra macro blocks is intelligently
  325. * chosen by encoder, but the number of forcely coded
  326. * intra macro blocks in a frame is guaranteed to be
  327. * equal to totalMbsInFrame/airMbPeriod
  328. */
  329. in_param->intra_refresh_method = 1;
  330. in_param->intra_frame_interval = 0;
  331. }
  332. }
  333. static void setup_params(GstDspBase *base)
  334. {
  335. struct in_params *in_param;
  336. struct out_params *out_param;
  337. du_port_t *p;
  338. p = base->ports[0];
  339. gstdsp_port_setup_params(base, p, sizeof(*in_param), setup_in_params);
  340. p->send_cb = in_send_cb;
  341. p = base->ports[1];
  342. gstdsp_port_setup_params(base, p, OUT_PARAMS_SIZE_VER(base, out_param), NULL);
  343. p->recv_cb = out_recv_cb;
  344. }
  345. struct td_codec td_h264enc_codec = {
  346. .uuid = &(const struct dsp_uuid) { 0x63A3581A, 0x09D7, 0x4AD0, 0x80, 0xB8,
  347. { 0x5F, 0x2C, 0x4D, 0x4D, 0x59, 0xC9 } },
  348. .filename = "h264venc_sn.dll64P",
  349. .setup_params = setup_params,
  350. .create_args = create_args,
  351. };