gstdspvenc.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*
  2. * Copyright (C) 2009-2010 Felipe Contreras
  3. *
  4. * Authors:
  5. * Felipe Contreras <felipe.contreras@gmail.com>
  6. * Juha Alanen <juha.m.alanen@nokia.com>
  7. *
  8. * This file may be used under the terms of the GNU Lesser General Public
  9. * License version 2.1, a copy of which is found in LICENSE included in the
  10. * packaging of this file.
  11. */
  12. #include "gstdspvenc.h"
  13. #include "plugin.h"
  14. #include "util.h"
  15. #include "dsp_bridge.h"
  16. #include <string.h> /* for memcpy */
  17. #include "log.h"
  18. #define GST_CAT_DEFAULT gstdsp_debug
  19. static GstDspBaseClass *parent_class;
  20. enum {
  21. ARG_0,
  22. ARG_BITRATE,
  23. ARG_MODE,
  24. ARG_KEYFRAME_INTERVAL,
  25. ARG_MAX_BITRATE,
  26. ARG_INTRA_REFRESH,
  27. };
  28. #define DEFAULT_BITRATE 0
  29. #define DEFAULT_MAX_BITRATE 0
  30. #define DEFAULT_MODE 0
  31. #define DEFAULT_KEYFRAME_INTERVAL 1
  32. #define DEFAULT_INTRA_REFRESH (DEFAULT_MODE == 1)
  33. #define GST_TYPE_DSPVENC_MODE gst_dspvenc_mode_get_type()
  34. static GType
  35. gst_dspvenc_mode_get_type(void)
  36. {
  37. static GType gst_dspvenc_mode_type;
  38. if (!gst_dspvenc_mode_type) {
  39. static GEnumValue modes[] = {
  40. {0, "Storage", "storage"},
  41. {1, "Streaming", "streaming"},
  42. {0, NULL, NULL},
  43. };
  44. gst_dspvenc_mode_type = g_enum_register_static("GstDspVEncMode", modes);
  45. }
  46. return gst_dspvenc_mode_type;
  47. }
  48. static inline GstCaps *
  49. generate_sink_template(void)
  50. {
  51. GstCaps *caps;
  52. GstStructure *struc;
  53. caps = gst_caps_new_empty();
  54. struc = gst_structure_new("video/x-raw-yuv",
  55. "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'),
  56. NULL);
  57. gst_caps_append_structure(caps, struc);
  58. struc = gst_structure_new("video/x-raw-yuv",
  59. "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('I', '4', '2', '0'),
  60. NULL);
  61. gst_caps_append_structure(caps, struc);
  62. return caps;
  63. }
  64. static inline void *
  65. create_node(GstDspVEnc *self)
  66. {
  67. GstDspBase *base;
  68. int dsp_handle;
  69. struct dsp_node *node;
  70. struct td_codec *codec;
  71. const struct dsp_uuid usn_uuid = { 0x79A3C8B3, 0x95F2, 0x403F, 0x9A, 0x4B,
  72. { 0xCF, 0x80, 0x57, 0x73, 0x05, 0x41 } };
  73. const struct dsp_uuid conversions_uuid = { 0x722DD0DA, 0xF532, 0x4238, 0xB8, 0x46,
  74. { 0xAB, 0xFF, 0x5D, 0xA4, 0xBA, 0x02 } };
  75. base = GST_DSP_BASE(self);
  76. dsp_handle = base->dsp_handle;
  77. if (!gstdsp_register(dsp_handle, &usn_uuid, DSP_DCD_LIBRARYTYPE, "usn.dll64P")) {
  78. pr_err(self, "failed to register usn node library");
  79. return NULL;
  80. }
  81. codec = base->codec;
  82. if (!codec) {
  83. pr_err(self, "unknown algorithm");
  84. return NULL;
  85. }
  86. if (!gstdsp_register(dsp_handle, codec->uuid, DSP_DCD_LIBRARYTYPE, codec->filename)) {
  87. pr_err(self, "failed to register algo node library");
  88. return NULL;
  89. }
  90. if (!gstdsp_register(dsp_handle, codec->uuid, DSP_DCD_NODETYPE, codec->filename)) {
  91. pr_err(self, "failed to register algo node");
  92. return NULL;
  93. }
  94. /* only needed for jpegenc */
  95. if (base->alg == GSTDSP_JPEGENC) {
  96. /* SN_API == 0 doesn't have it, so don't fail */
  97. (void) gstdsp_register(dsp_handle, &conversions_uuid, DSP_DCD_LIBRARYTYPE, "conversions.dll64P");
  98. }
  99. if(sn_exist("conversions.dll64P"))
  100. #if SN_API >= 2
  101. base->sn_api=2;
  102. #else
  103. base->sn_api=1;
  104. #endif
  105. else
  106. base->sn_api=0;
  107. {
  108. struct dsp_node_attr_in attrs = {
  109. .cb = sizeof(attrs),
  110. .priority = 5,
  111. .timeout = 1000,
  112. };
  113. void *arg_data;
  114. codec->create_args(base, &attrs.profile_id, &arg_data);
  115. if (!arg_data)
  116. return NULL;
  117. if (!dsp_node_allocate(dsp_handle, base->proc, codec->uuid, arg_data, &attrs, &node)) {
  118. pr_err(self, "dsp node allocate failed");
  119. free(arg_data);
  120. return NULL;
  121. }
  122. free(arg_data);
  123. }
  124. if (!dsp_node_create(dsp_handle, node)) {
  125. pr_err(self, "dsp node create failed");
  126. dsp_node_free(dsp_handle, node);
  127. return NULL;
  128. }
  129. pr_info(self, "dsp node created");
  130. return node;
  131. }
  132. static void check_supported_levels(GstDspVEnc *self, gint tgt_level)
  133. {
  134. guint i;
  135. gint tgt_mbps, tgt_mbpf, tgt_bitrate;
  136. struct gstdsp_codec_level *cur, *level;
  137. if (!self->supported_levels)
  138. return;
  139. tgt_bitrate = self->user_max_bitrate;
  140. tgt_mbpf = ROUND_UP(self->width, 16) / 16 * ROUND_UP(self->height, 16) / 16;
  141. tgt_mbps = tgt_mbpf * self->framerate;
  142. if (!tgt_bitrate)
  143. tgt_bitrate = self->bitrate;
  144. search:
  145. level = cur = self->supported_levels;
  146. for (i = 0; i < self->nr_supported_levels; i++, cur++) {
  147. bool ok = false;
  148. /* is this the level we want? */
  149. if (tgt_level > 0 && tgt_level != cur->id)
  150. continue;
  151. /* is the bitrate enough? (and doesn't overshoot) */
  152. if (tgt_bitrate && cur->bitrate >= tgt_bitrate && level->bitrate < tgt_bitrate)
  153. ok = true;
  154. /* are the mbps enough? (and don't overshoot) */
  155. if (cur->mbps >= tgt_mbps && level->mbps < tgt_mbps)
  156. ok = true;
  157. /* at same level of mbps, get the biggest bitrate */
  158. if (cur->mbps >= tgt_mbps && cur->mbps == level->mbps &&
  159. !tgt_bitrate && cur->bitrate >= level->bitrate)
  160. ok = true;
  161. /* are the mbpf enough? (and don't overshoot) */
  162. if (cur->mbpf >= tgt_mbpf && level->mbpf < tgt_mbpf)
  163. ok = true;
  164. if (!ok)
  165. continue;
  166. /* we got a winner */
  167. level = cur;
  168. }
  169. if (tgt_level > 0 && tgt_level != level->id) {
  170. pr_warning(self, "invalid level: %d; ignoring", tgt_level);
  171. tgt_level = -1;
  172. goto search;
  173. }
  174. /* went beyond the table looking for a target; pick last one */
  175. if ((tgt_bitrate && level->bitrate < tgt_bitrate) || (level->mbps < tgt_mbps)) {
  176. if (tgt_level > 0) {
  177. pr_warning(self, "invalid level: %d; ignoring", tgt_level);
  178. tgt_level = -1;
  179. goto search;
  180. } else
  181. level = --cur;
  182. }
  183. if (!self->user_max_bitrate || self->user_max_bitrate >= level->bitrate)
  184. self->max_bitrate = level->bitrate;
  185. else
  186. self->max_bitrate = self->user_max_bitrate;
  187. self->level = level->id;
  188. pr_info(self, "level bitrate: %d", level->bitrate);
  189. pr_info(self, "max bitrate: %d", self->max_bitrate);
  190. pr_info(self, "level: %d", self->level);
  191. }
  192. static gboolean
  193. sink_setcaps(GstPad *pad,
  194. GstCaps *caps)
  195. {
  196. GstDspVEnc *self;
  197. GstDspBase *base;
  198. GstStructure *in_struc;
  199. GstCaps *out_caps;
  200. GstStructure *out_struc;
  201. gint width = 0, height = 0;
  202. GstCaps *allowed_caps;
  203. gint tgt_level = -1;
  204. struct td_codec *codec;
  205. gint owidth, oheight;
  206. self = GST_DSP_VENC(GST_PAD_PARENT(pad));
  207. base = GST_DSP_BASE(self);
  208. codec = base->codec;
  209. if (!codec)
  210. return FALSE;
  211. #ifdef DEBUG
  212. {
  213. gchar *str = gst_caps_to_string(caps);
  214. pr_info(self, "sink caps: %s", str);
  215. g_free(str);
  216. }
  217. #endif
  218. in_struc = gst_caps_get_structure(caps, 0);
  219. out_caps = gst_caps_new_empty();
  220. switch (base->alg) {
  221. case GSTDSP_JPEGENC:
  222. out_struc = gst_structure_new("image/jpeg",
  223. NULL);
  224. break;
  225. case GSTDSP_H263ENC:
  226. case GSTDSP_H263P0ENC:
  227. out_struc = gst_structure_new("video/x-h263",
  228. "variant", G_TYPE_STRING, "itu",
  229. NULL);
  230. break;
  231. case GSTDSP_HDMP4VENC:
  232. case GSTDSP_MP4VENC:
  233. out_struc = gst_structure_new("video/mpeg",
  234. "mpegversion", G_TYPE_INT, 4,
  235. "systemstream", G_TYPE_BOOLEAN, FALSE,
  236. NULL);
  237. break;
  238. case GSTDSP_H264ENC:
  239. case GSTDSP_HDH264ENC:
  240. out_struc = gst_structure_new("video/x-h264",
  241. "alignment", G_TYPE_STRING, "au",
  242. NULL);
  243. break;
  244. default:
  245. return FALSE;
  246. }
  247. if (gst_structure_get_int(in_struc, "width", &width))
  248. gst_structure_set(out_struc, "width", G_TYPE_INT, width, NULL);
  249. if (gst_structure_get_int(in_struc, "height", &height))
  250. gst_structure_set(out_struc, "height", G_TYPE_INT, height, NULL);
  251. gst_structure_get_fourcc(in_struc, "format", &self->color_format);
  252. switch (base->alg) {
  253. case GSTDSP_H263ENC:
  254. case GSTDSP_MP4VENC:
  255. case GSTDSP_H264ENC:
  256. base->output_buffer_size = width * height / 2;
  257. break;
  258. case GSTDSP_JPEGENC:
  259. if (width % 2 || height % 2)
  260. return FALSE;
  261. if (self->color_format == GST_MAKE_FOURCC('I', '4', '2', '0'))
  262. base->input_buffer_size = ROUND_UP(width, 16) * ROUND_UP(height, 16) * 3 / 2;
  263. else
  264. base->input_buffer_size = ROUND_UP(width, 16) * ROUND_UP(height, 16) * 2;
  265. base->output_buffer_size = width * height;
  266. if (self->quality < 10)
  267. base->output_buffer_size /= 10;
  268. else if (self->quality < 100)
  269. base->output_buffer_size /= (100 / self->quality);
  270. break;
  271. default:
  272. break;
  273. }
  274. owidth = self->width;
  275. oheight = self->height;
  276. self->width = width;
  277. self->height = height;
  278. {
  279. const GValue *framerate = NULL;
  280. framerate = gst_structure_get_value(in_struc, "framerate");
  281. if (framerate) {
  282. gst_structure_set_value(out_struc, "framerate", framerate);
  283. /* calculate nearest integer */
  284. self->framerate = (gst_value_get_fraction_numerator(framerate) * 2 /
  285. gst_value_get_fraction_denominator(framerate) + 1) / 2;
  286. }
  287. }
  288. /* see if downstream caps express something */
  289. allowed_caps = gst_pad_get_allowed_caps(base->srcpad);
  290. if (allowed_caps) {
  291. if (gst_caps_get_size(allowed_caps) > 0) {
  292. GstStructure *s;
  293. s = gst_caps_get_structure(allowed_caps, 0);
  294. gst_structure_get_int(s, "level", &tgt_level);
  295. if (base->alg == GSTDSP_H264ENC || base->alg == GSTDSP_HDH264ENC) {
  296. const char *stream_format;
  297. stream_format = gst_structure_get_string(s, "stream-format");
  298. if (stream_format && !strcmp(stream_format, "avc"))
  299. self->priv.h264.bytestream = false;
  300. else
  301. stream_format = "byte-stream";
  302. gst_structure_set(out_struc, "stream-format", G_TYPE_STRING, stream_format, NULL);
  303. }
  304. }
  305. gst_caps_unref(allowed_caps);
  306. }
  307. check_supported_levels(self, tgt_level);
  308. if (self->bitrate == 0)
  309. self->bitrate = self->max_bitrate;
  310. else if (self->bitrate > self->max_bitrate)
  311. self->bitrate = self->max_bitrate;
  312. gst_caps_append_structure(out_caps, out_struc);
  313. #ifdef DEBUG
  314. {
  315. gchar *str = gst_caps_to_string(out_caps);
  316. pr_info(self, "src caps: %s", str);
  317. g_free(str);
  318. }
  319. #endif
  320. if (!gst_pad_take_caps(base->srcpad, out_caps))
  321. return FALSE;
  322. if (gstdsp_need_node_reset(base, caps, owidth, oheight)) {
  323. /* flush pending frames if needed */
  324. if (base->flush_buffer) {
  325. pr_debug(self, "flushing pending");
  326. base->flush_buffer(base);
  327. }
  328. /* wait (some time) for all to have been pushed */
  329. g_mutex_lock(base->ts_mutex);
  330. while (base->ts_count > 0) {
  331. GTimeVal tv = {1, 0};
  332. if (!g_cond_timed_wait(base->ts_cond, base->ts_mutex, &tv)) {
  333. pr_info(self, "timeout waiting for all buffers pushed");
  334. break;
  335. }
  336. }
  337. g_mutex_unlock(base->ts_mutex);
  338. gstdsp_reinit(base);
  339. }
  340. if (base->node)
  341. return TRUE;
  342. switch (base->alg) {
  343. case GSTDSP_JPEGENC:
  344. du_port_alloc_buffers(base->ports[0], 1);
  345. du_port_alloc_buffers(base->ports[1], 2);
  346. break;
  347. case GSTDSP_HDMP4VENC:
  348. case GSTDSP_HDH264ENC:
  349. du_port_alloc_buffers(base->ports[0], 6);
  350. du_port_alloc_buffers(base->ports[1], 8);
  351. break;
  352. default:
  353. du_port_alloc_buffers(base->ports[0], 2);
  354. du_port_alloc_buffers(base->ports[1], 4);
  355. break;
  356. }
  357. base->node = create_node(self);
  358. if (!base->node) {
  359. pr_err(self, "dsp node creation failed");
  360. return FALSE;
  361. }
  362. if (codec->setup_params)
  363. codec->setup_params(base);
  364. if (!gstdsp_start(base)) {
  365. pr_err(self, "dsp start failed");
  366. return FALSE;
  367. }
  368. if (codec->send_params)
  369. codec->send_params(base, base->node);
  370. return TRUE;
  371. }
  372. static gboolean
  373. sink_event(GstDspBase *base,
  374. GstEvent *event)
  375. {
  376. GstDspVEnc *self = GST_DSP_VENC(base);
  377. switch (GST_EVENT_TYPE(event)) {
  378. case GST_EVENT_CUSTOM_DOWNSTREAM:
  379. {
  380. const GstStructure *s;
  381. s = gst_event_get_structure(event);
  382. if (gst_structure_has_name(s, "GstForceKeyUnit")) {
  383. g_mutex_lock(self->keyframe_mutex);
  384. if (self->keyframe_event)
  385. gst_event_unref(self->keyframe_event);
  386. self->keyframe_event = event;
  387. g_mutex_unlock(self->keyframe_mutex);
  388. return TRUE;
  389. }
  390. break;
  391. }
  392. default:
  393. break;
  394. }
  395. if (parent_class->sink_event)
  396. return parent_class->sink_event(base, event);
  397. return gst_pad_push_event(base->srcpad, event);
  398. }
  399. static gboolean
  400. src_event(GstDspBase *base,
  401. GstEvent *event)
  402. {
  403. GstDspVEnc *self = GST_DSP_VENC(base);
  404. switch (GST_EVENT_TYPE(event)) {
  405. case GST_EVENT_CUSTOM_UPSTREAM:
  406. {
  407. const GstStructure *s;
  408. s = gst_event_get_structure(event);
  409. if (gst_structure_has_name(s, "GstForceKeyUnit")) {
  410. g_mutex_lock(self->keyframe_mutex);
  411. /* make it downstream */
  412. GST_EVENT_TYPE(event) = GST_EVENT_CUSTOM_DOWNSTREAM;
  413. if (self->keyframe_event)
  414. gst_event_unref(self->keyframe_event);
  415. self->keyframe_event = event;
  416. g_mutex_unlock(self->keyframe_mutex);
  417. return TRUE;
  418. }
  419. break;
  420. }
  421. default:
  422. break;
  423. }
  424. if (parent_class->src_event)
  425. return parent_class->src_event(base, event);
  426. return gst_pad_push_event(base->sinkpad, event);
  427. }
  428. static void
  429. set_property(GObject *obj,
  430. guint prop_id,
  431. const GValue *value,
  432. GParamSpec *pspec)
  433. {
  434. GstDspVEnc *self = GST_DSP_VENC(obj);
  435. switch (prop_id) {
  436. case ARG_BITRATE: {
  437. guint bitrate;
  438. bitrate = g_value_get_uint(value);
  439. if (self->max_bitrate && bitrate > (unsigned) self->max_bitrate)
  440. bitrate = self->max_bitrate;
  441. g_atomic_int_set(&self->bitrate, bitrate);
  442. break;
  443. }
  444. case ARG_MODE:
  445. self->mode = g_value_get_enum(value);
  446. /* guess intra-refresh, if not manually set */
  447. if (self->intra_refresh_set)
  448. break;
  449. self->intra_refresh = (self->mode == 1);
  450. break;
  451. case ARG_KEYFRAME_INTERVAL:
  452. g_atomic_int_set(&self->keyframe_interval, g_value_get_int(value));
  453. break;
  454. case ARG_MAX_BITRATE:
  455. self->user_max_bitrate = g_value_get_uint(value);
  456. break;
  457. case ARG_INTRA_REFRESH:
  458. self->intra_refresh = g_value_get_boolean(value);
  459. self->intra_refresh_set = true;
  460. break;
  461. default:
  462. G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
  463. break;
  464. }
  465. }
  466. static void
  467. get_property(GObject *obj,
  468. guint prop_id,
  469. GValue *value,
  470. GParamSpec *pspec)
  471. {
  472. GstDspVEnc *self = GST_DSP_VENC(obj);
  473. switch (prop_id) {
  474. case ARG_BITRATE:
  475. g_value_set_uint(value, g_atomic_int_get(&self->bitrate));
  476. break;
  477. case ARG_MODE:
  478. g_value_set_enum(value, self->mode);
  479. break;
  480. case ARG_KEYFRAME_INTERVAL:
  481. g_value_set_int(value, g_atomic_int_get(&self->keyframe_interval));
  482. break;
  483. case ARG_MAX_BITRATE: {
  484. guint bitrate;
  485. bitrate = self->user_max_bitrate;
  486. if (!bitrate)
  487. bitrate = self->max_bitrate;
  488. g_value_set_uint(value, bitrate);
  489. break;
  490. }
  491. case ARG_INTRA_REFRESH:
  492. g_value_set_boolean(value, self->intra_refresh);
  493. break;
  494. default:
  495. G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
  496. break;
  497. }
  498. }
  499. static void
  500. reset(GstDspBase *base)
  501. {
  502. GstDspVEnc *self = GST_DSP_VENC(base);
  503. pr_debug(self, "venc reset");
  504. /* some cleanup */
  505. if (base->alg == GSTDSP_H264ENC || base->alg == GSTDSP_HDH264ENC) {
  506. self->priv.h264.codec_data_done = FALSE;
  507. self->priv.h264.sps_received = FALSE;
  508. self->priv.h264.pps_received = FALSE;
  509. gst_buffer_replace(&self->priv.h264.sps, NULL);
  510. gst_buffer_replace(&self->priv.h264.pps, NULL);
  511. gst_buffer_replace(&self->priv.h264.codec_data, NULL);
  512. } else {
  513. self->priv.mpeg4.codec_data_done = FALSE;
  514. self->priv.mpeg4.vbv_size = 0;
  515. }
  516. }
  517. static void
  518. instance_init(GTypeInstance *instance,
  519. gpointer g_class)
  520. {
  521. GstDspBase *base = GST_DSP_BASE(instance);
  522. GstDspVEnc *self = GST_DSP_VENC(instance);
  523. gst_pad_set_setcaps_function(base->sinkpad, sink_setcaps);
  524. base->reset = reset;
  525. self->bitrate = DEFAULT_BITRATE;
  526. self->mode = DEFAULT_MODE;
  527. self->keyframe_interval = DEFAULT_KEYFRAME_INTERVAL;
  528. self->intra_refresh = DEFAULT_INTRA_REFRESH;
  529. self->keyframe_mutex = g_mutex_new();
  530. }
  531. static void
  532. finalize(GObject *obj)
  533. {
  534. GstDspVEnc *self = GST_DSP_VENC(obj);
  535. g_mutex_free(self->keyframe_mutex);
  536. if (self->keyframe_event)
  537. gst_event_unref(self->keyframe_event);
  538. G_OBJECT_CLASS(parent_class)->finalize(obj);
  539. }
  540. static void
  541. base_init(gpointer g_class)
  542. {
  543. GstElementClass *element_class;
  544. GstPadTemplate *template;
  545. element_class = GST_ELEMENT_CLASS(g_class);
  546. template = gst_pad_template_new("sink", GST_PAD_SINK,
  547. GST_PAD_ALWAYS,
  548. generate_sink_template());
  549. gst_element_class_add_pad_template(element_class, template);
  550. gst_object_unref(template);
  551. }
  552. static void
  553. class_init(gpointer g_class,
  554. gpointer class_data)
  555. {
  556. GObjectClass *gobject_class;
  557. GstDspBaseClass *base_class;
  558. parent_class = g_type_class_peek_parent(g_class);
  559. gobject_class = G_OBJECT_CLASS(g_class);
  560. base_class = GST_DSP_BASE_CLASS(g_class);
  561. gobject_class->set_property = set_property;
  562. gobject_class->get_property = get_property;
  563. g_object_class_install_property(gobject_class, ARG_BITRATE,
  564. g_param_spec_uint("bitrate", "Bit-rate",
  565. "Encoding bit-rate (0 for auto)",
  566. 0, G_MAXUINT, DEFAULT_BITRATE,
  567. G_PARAM_READWRITE));
  568. g_object_class_install_property(gobject_class, ARG_MODE,
  569. g_param_spec_enum("mode", "Encoding mode",
  570. "Encoding mode",
  571. GST_TYPE_DSPVENC_MODE,
  572. DEFAULT_MODE,
  573. G_PARAM_READWRITE));
  574. g_object_class_install_property(gobject_class, ARG_KEYFRAME_INTERVAL,
  575. g_param_spec_int("keyframe-interval", "Keyframe interval",
  576. "Generate keyframes at every specified intervals (seconds)",
  577. 0, G_MAXINT, DEFAULT_KEYFRAME_INTERVAL, G_PARAM_READWRITE));
  578. g_object_class_install_property(gobject_class, ARG_MAX_BITRATE,
  579. g_param_spec_uint("max-bitrate", "Maximum Bit-rate",
  580. "Maximum Encoding bit-rate (0 for auto)",
  581. 0, G_MAXUINT, DEFAULT_MAX_BITRATE,
  582. G_PARAM_READWRITE));
  583. g_object_class_install_property(gobject_class, ARG_INTRA_REFRESH,
  584. g_param_spec_boolean("intra-refresh", "Intra-refresh",
  585. "Whether or not to use periodic intra-refresh",
  586. DEFAULT_INTRA_REFRESH, G_PARAM_READWRITE));
  587. gobject_class->finalize = finalize;
  588. base_class->src_event = src_event;
  589. base_class->sink_event = sink_event;
  590. }
  591. GType
  592. gst_dsp_venc_get_type(void)
  593. {
  594. static GType type;
  595. if (G_UNLIKELY(type == 0)) {
  596. GTypeInfo type_info = {
  597. .class_size = sizeof(GstDspVEncClass),
  598. .class_init = class_init,
  599. .base_init = base_init,
  600. .instance_size = sizeof(GstDspVEnc),
  601. .instance_init = instance_init,
  602. };
  603. type = g_type_register_static(GST_DSP_BASE_TYPE, "GstDspVEnc", &type_info, 0);
  604. }
  605. return type;
  606. }