12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496 |
- /*
- * Copyright (C) 2009-2010 Felipe Contreras
- *
- * Authors:
- * Felipe Contreras <felipe.contreras@gmail.com>
- * Juha Alanen <juha.m.alanen@nokia.com>
- *
- * This file may be used under the terms of the GNU Lesser General Public
- * License version 2.1, a copy of which is found in LICENSE included in the
- * packaging of this file.
- */
- #include "gstdspvenc.h"
- #include "plugin.h"
- #include "util.h"
- #include "dsp_bridge.h"
- #include <string.h> /* for memcpy */
- #include "log.h"
- #define GST_CAT_DEFAULT gstdsp_debug
- static GstDspBaseClass *parent_class;
- enum {
- ARG_0,
- ARG_BITRATE,
- ARG_MODE,
- ARG_KEYFRAME_INTERVAL,
- ARG_MAX_BITRATE,
- ARG_INTRA_REFRESH,
- };
- #define DEFAULT_BITRATE 0
- #define DEFAULT_MAX_BITRATE 0
- #define DEFAULT_MODE 0
- #define DEFAULT_KEYFRAME_INTERVAL 1
- #define DEFAULT_INTRA_REFRESH false
- #define GST_TYPE_DSPVENC_MODE gst_dspvenc_mode_get_type()
- static GType
- gst_dspvenc_mode_get_type(void)
- {
- static GType gst_dspvenc_mode_type;
- if (!gst_dspvenc_mode_type) {
- static GEnumValue modes[] = {
- {0, "Storage", "storage"},
- {1, "Streaming", "streaming"},
- {0, NULL, NULL},
- };
- gst_dspvenc_mode_type = g_enum_register_static("GstDspVEncMode", modes);
- }
- return gst_dspvenc_mode_type;
- }
- static inline GstCaps *
- generate_sink_template(void)
- {
- GstCaps *caps;
- GstStructure *struc;
- caps = gst_caps_new_empty();
- struc = gst_structure_new("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('U', 'Y', 'V', 'Y'),
- NULL);
- gst_caps_append_structure(caps, struc);
- struc = gst_structure_new("video/x-raw-yuv",
- "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('I', '4', '2', '0'),
- NULL);
- gst_caps_append_structure(caps, struc);
- return caps;
- }
- struct foo_data {
- unsigned long size;
- unsigned short data[42];
- };
- struct jpegenc_args {
- uint16_t num_streams;
- uint16_t in_id;
- uint16_t in_type;
- uint16_t in_count;
- uint16_t out_id;
- uint16_t out_type;
- uint16_t out_count;
- uint16_t max_width;
- uint16_t max_height;
- uint16_t color_format;
- uint16_t max_app0_width;
- uint16_t max_app0_height;
- uint16_t max_app1_width;
- uint16_t max_app1_height;
- uint16_t max_app13_width;
- uint16_t max_app13_height;
- uint16_t scans;
- /* SN_API >= 1 */
- uint16_t convert;
- uint16_t max_app5_width;
- uint16_t max_app5_height;
- };
- #include "gstdspjpegenc.h"
- static inline void *
- get_jpegenc_args(GstDspVEnc *self)
- {
- GstDspBase *base = GST_DSP_BASE(self);
- struct jpegenc_args args = {
- .num_streams = 2,
- .in_id = 0,
- .in_type = 0,
- .in_count = base->ports[0]->num_buffers,
- .out_id = 1,
- .out_type = 0,
- .out_count = base->ports[1]->num_buffers,
- .max_width = JPEGENC_MAX_WIDTH + 32,
- .max_height = JPEGENC_MAX_HEIGHT + 32,
- .color_format = 1,
- };
- struct foo_data *cb_data;
- cb_data = malloc(sizeof(*cb_data));
- cb_data->size = sizeof(args);
- memcpy(&cb_data->data, &args, sizeof(args));
- return cb_data;
- }
- struct mp4venc_args {
- uint16_t num_streams;
- uint16_t in_id;
- uint16_t in_type;
- uint16_t in_count;
- uint16_t out_id;
- uint16_t out_type;
- uint16_t out_count;
- uint16_t reserved;
- uint32_t width;
- uint32_t height;
- uint32_t bitrate;
- uint32_t vbv_size;
- uint32_t gob_interval;
- uint8_t is_mpeg4;
- uint8_t color_format;
- uint8_t hec;
- uint8_t resync_marker;
- uint8_t data_part;
- uint8_t reversible_vlc;
- uint8_t unrestricted_mv;
- uint8_t framerate;
- uint8_t rate_control;
- uint8_t qp_first;
- uint8_t profile;
- uint8_t level;
- uint32_t max_delay;
- uint32_t vbv_enable;
- uint32_t h263_slice_mode;
- uint32_t use_gov;
- uint32_t use_vos;
- uint32_t h263_annex_i;
- uint32_t h263_annex_j;
- uint32_t h263_annex_t;
- };
- static inline void *
- get_mp4venc_args(GstDspVEnc *self)
- {
- GstDspBase *base = GST_DSP_BASE(self);
- struct mp4venc_args args = {
- .num_streams = 2,
- .in_id = 0,
- .in_type = 0,
- .in_count = base->ports[0]->num_buffers,
- .out_id = 1,
- .out_type = 0,
- .out_count = base->ports[1]->num_buffers,
- .width = self->width,
- .height = self->height,
- .bitrate = self->bitrate,
- .vbv_size = 112,
- .color_format = (self->color_format == GST_MAKE_FOURCC('U','Y','V','Y') ? 2 : 0),
- .unrestricted_mv = 1,
- .framerate = self->framerate,
- .qp_first = 12,
- .profile = 1,
- .max_delay = 300,
- .vbv_enable = 1,
- .use_vos = 1,
- };
- args.is_mpeg4 = base->alg == GSTDSP_MP4VENC ? 1 : 0;
- if (base->alg == GSTDSP_MP4VENC)
- args.level = 5;
- else
- args.level = 20;
- if (self->mode == 0) {
- args.gob_interval = 0;
- args.hec = 0;
- args.resync_marker = 0;
- args.rate_control = 2;
- } else {
- args.gob_interval = 1;
- args.hec = 1;
- args.resync_marker = 1;
- args.rate_control = 1;
- }
- struct foo_data *cb_data;
- cb_data = malloc(sizeof(*cb_data));
- cb_data->size = sizeof(args);
- memcpy(&cb_data->data, &args, sizeof(args));
- return cb_data;
- }
- struct h264venc_args {
- uint16_t num_streams;
- uint16_t in_id;
- uint16_t in_type;
- uint16_t in_count;
- uint16_t out_id;
- uint16_t out_type;
- uint16_t out_count;
- uint16_t reserved;
- uint32_t width;
- uint32_t height;
- uint32_t bitrate;
- uint32_t bitstream_buf_size;
- uint32_t intra_frame_period;
- uint32_t framerate;
- uint8_t yuv_format;
- uint8_t unrestricted_mv; /* not supported */
- uint8_t num_ref_frames; /* not supported */
- uint8_t rc_algorithm;
- uint8_t idr_enable; /* not used */
- uint8_t deblocking_enable;
- uint8_t mv_range;
- uint8_t qpi_frame;
- uint8_t profile;
- uint8_t level;
- uint16_t nal_mode;
- uint32_t encoding_preset;
- uint32_t rc_algo;
- };
- static inline void *
- get_h264venc_args(GstDspVEnc *self)
- {
- GstDspBase *base = GST_DSP_BASE(self);
- struct h264venc_args args = {
- .num_streams = 2,
- .in_id = 0,
- .in_type = 0,
- .in_count = base->ports[0]->num_buffers,
- .out_id = 1,
- .out_type = 0,
- .out_count = base->ports[1]->num_buffers,
- .width = self->width,
- .height = self->height,
- .bitrate = self->bitrate,
- .bitstream_buf_size = base->output_buffer_size,
- .intra_frame_period = self->framerate,
- .framerate = self->framerate * 1000,
- .yuv_format = (self->color_format == GST_MAKE_FOURCC('U','Y','V','Y') ? 2 : 0),
- .num_ref_frames = 1, /* not supported */
- .rc_algorithm = 1, /* 0 = var, 1 == constant, 2 == none */
- .deblocking_enable = 1,
- .mv_range = 64,
- .qpi_frame = 28,
- .profile = 66, /* Baseline profile */
- .level = 13,
- .nal_mode = self->priv.h264.bytestream ? 2 : 1, /* 0 == bytestream, 1 == NALU, 2 == bytestream, with NALU sizes */
- .encoding_preset = 3,
- };
- if (self->mode == 0)
- args.rc_algorithm = 0; /* storage VBR */
- else
- args.rc_algorithm = 1; /* low delay CBR */
- struct foo_data *cb_data;
- cb_data = malloc(sizeof(*cb_data));
- cb_data->size = sizeof(args);
- memcpy(&cb_data->data, &args, sizeof(args));
- return cb_data;
- }
- static inline void *
- create_node(GstDspVEnc *self)
- {
- GstDspBase *base;
- int dsp_handle;
- struct dsp_node *node;
- const struct dsp_uuid *alg_uuid;
- const char *alg_fn;
- const struct dsp_uuid usn_uuid = { 0x79A3C8B3, 0x95F2, 0x403F, 0x9A, 0x4B,
- { 0xCF, 0x80, 0x57, 0x73, 0x05, 0x41 } };
- const struct dsp_uuid jpeg_enc_uuid = { 0xcb70c0c1, 0x4c85, 0x11d6, 0xb1, 0x05,
- { 0x00, 0xc0, 0x4f, 0x32, 0x90, 0x31 } };
- const struct dsp_uuid mp4v_enc_uuid = { 0x98c2e8d8, 0x4644, 0x11d6, 0x81, 0x18,
- { 0x00, 0xb0, 0xd0, 0x8d, 0x72, 0x9f } };
- const struct dsp_uuid h264_enc_uuid = { 0x63A3581A, 0x09D7, 0x4AD0, 0x80, 0xB8,
- { 0x5F, 0x2C, 0x4D, 0x4D, 0x59, 0xC9 } };
- const struct dsp_uuid conversions_uuid = { 0x722DD0DA, 0xF532, 0x4238, 0xB8, 0x46,
- { 0xAB, 0xFF, 0x5D, 0xA4, 0xBA, 0x02 } };
- base = GST_DSP_BASE(self);
- dsp_handle = base->dsp_handle;
- if (!gstdsp_register(dsp_handle, &usn_uuid, DSP_DCD_LIBRARYTYPE, "usn.dll64P")) {
- pr_err(self, "failed to register usn node library");
- return NULL;
- }
- switch (base->alg) {
- case GSTDSP_JPEGENC:
- alg_uuid = &jpeg_enc_uuid;
- alg_fn = "jpegenc_sn.dll64P";
- break;
- case GSTDSP_H263ENC:
- case GSTDSP_MP4VENC:
- alg_uuid = &mp4v_enc_uuid;
- alg_fn = "m4venc_sn.dll64P";
- break;
- case GSTDSP_H264ENC:
- alg_uuid = &h264_enc_uuid;
- alg_fn = "h264venc_sn.dll64P";
- break;
- default:
- pr_err(self, "unknown algorithm");
- return NULL;
- }
- if (!gstdsp_register(dsp_handle, alg_uuid, DSP_DCD_LIBRARYTYPE, alg_fn)) {
- pr_err(self, "failed to register algo node library");
- return NULL;
- }
- if (!gstdsp_register(dsp_handle, alg_uuid, DSP_DCD_NODETYPE, alg_fn)) {
- pr_err(self, "failed to register algo node");
- return NULL;
- }
- /* only needed for jpegenc */
- if (base->alg == GSTDSP_JPEGENC) {
- /* SN_API == 0 doesn't have it, so don't fail */
- gstdsp_register(dsp_handle, &conversions_uuid, DSP_DCD_LIBRARYTYPE, "conversions.dll64P");
- }
- {
- struct dsp_node_attr_in attrs = {
- .cb = sizeof(attrs),
- .priority = 5,
- .timeout = 1000,
- };
- void *cb_data;
- switch (base->alg) {
- case GSTDSP_JPEGENC:
- attrs.profile_id = 1;
- cb_data = get_jpegenc_args(self);
- break;
- case GSTDSP_H263ENC:
- case GSTDSP_MP4VENC:
- if (self->width * self->height > 720 * 480)
- attrs.profile_id = 4;
- else if (self->width * self->height > 640 * 480)
- attrs.profile_id = 3;
- else if (self->width * self->height > 352 * 288)
- attrs.profile_id = 2;
- else if (self->width * self->height > 176 * 144)
- attrs.profile_id = 1;
- else
- attrs.profile_id = 0;
- cb_data = get_mp4venc_args(self);
- break;
- case GSTDSP_H264ENC:
- if (self->width * self->height > 352 * 288)
- attrs.profile_id = 2;
- else if (self->width * self->height > 176 * 144)
- attrs.profile_id = 1;
- else
- attrs.profile_id = 0;
- cb_data = get_h264venc_args(self);
- break;
- default:
- cb_data = NULL;
- }
- if (!dsp_node_allocate(dsp_handle, base->proc, alg_uuid, cb_data, &attrs, &node)) {
- pr_err(self, "dsp node allocate failed");
- free(cb_data);
- return NULL;
- }
- free(cb_data);
- }
- if (!dsp_node_create(dsp_handle, node)) {
- pr_err(self, "dsp node create failed");
- dsp_node_free(dsp_handle, node);
- return NULL;
- }
- pr_info(self, "dsp node created");
- return node;
- }
- struct jpegenc_dyn_params {
- uint32_t size;
- uint32_t num_au; /* set to 0 */
- uint32_t color_format;
- uint32_t height;
- uint32_t width;
- uint32_t capture_width;
- uint32_t gen_header;
- uint32_t quality;
- uint32_t capture_height;
- uint32_t dri_interval;
- uint32_t huffman_table;
- uint32_t quant_table;
- /* SN_API == 1; apparently only sizes 32 and 52 work. */
- uint32_t resize;
- };
- static inline void
- jpegenc_send_params(GstDspBase *base)
- {
- struct jpegenc_dyn_params *params;
- dmm_buffer_t *b;
- GstDspVEnc *self = GST_DSP_VENC(base);
- b = dmm_buffer_calloc(base->dsp_handle, base->proc,
- sizeof(*params), DMA_TO_DEVICE);
- params = b->data;
- params->size = sizeof(*params);
- params->color_format = (self->color_format == GST_MAKE_FOURCC('U','Y','V','Y') ? 4 : 1);
- params->width = self->width;
- params->height = self->height;
- params->capture_width = self->width;
- params->quality = self->quality;
- params->capture_height = self->height;
- gstdsp_send_alg_ctrl(base, base->node, b);
- }
- struct h264venc_in_stream_params {
- uint32_t params_size;
- uint32_t input_height;
- uint32_t input_width;
- uint32_t ref_framerate;
- uint32_t target_framerate;
- uint32_t target_bitrate;
- uint32_t intra_frame_interval;
- uint32_t generate_header;
- uint32_t capture_width;
- uint32_t force_i_frame;
- uint32_t qp_intra;
- uint32_t qp_inter;
- uint32_t qp_max;
- uint32_t qp_min;
- uint32_t lf_disable_idc;
- uint32_t quarter_pel_disable;
- uint32_t air_mb_period;
- uint32_t max_mbs_per_slice;
- uint32_t max_bytes_per_slice;
- uint32_t slice_refresh_row_start_number;
- uint32_t slice_refresh_row_number;
- uint32_t filter_offset_a;
- uint32_t filter_offset_b;
- uint32_t log2MaxFNumMinus4;
- uint32_t chroma_qpi_index_offset;
- uint32_t constrained_intra_pred_enable;
- uint32_t pic_order_count_type;
- uint32_t max_mv_per_mb;
- uint32_t intra_4x4_enable_idc;
- uint32_t mv_data_enable;
- uint32_t hier_coding_enable;
- uint32_t stream_format;
- uint32_t intra_refresh_method;
- uint32_t perceptual_quant;
- uint32_t scene_change_det;
- void (*nal_callback_func)(uint32_t *buf, uint32_t *buf_size, void *context);
- void *context;
- uint32_t num_slice_aso;
- uint32_t aso_slice_order[8]; /* MAXNUMSLCGPS = 8 */
- uint32_t num_slice_groups;
- uint32_t slice_group_map_type;
- uint32_t slice_group_change_direction_flag;
- uint32_t slice_group_change_rate;
- uint32_t slice_group_change_cycle;
- uint32_t slice_group_params[8]; /* MAXNUMSLCGPS = 8 */
- uint32_t frame_index;
- };
- struct h264venc_out_stream_params {
- uint32_t bitstream_size;
- int32_t frame_type;
- uint32_t nalus_per_frame;
- uint32_t nalu_sizes[1618];
- uint32_t frame_index; /* Gives the number of the input frame which NAL unit belongs */
- uint32_t nalu_index; /* Number of current NAL unit inside the frame */
- };
- static void
- h264venc_in_send_cb(GstDspBase *base,
- du_port_t *port,
- dmm_buffer_t *p,
- dmm_buffer_t *b)
- {
- struct h264venc_in_stream_params *param;
- GstDspVEnc *self = GST_DSP_VENC(base);
- param = p->data;
- param->frame_index = g_atomic_int_exchange_and_add(&self->frame_index, 1);
- param->target_bitrate = g_atomic_int_get(&self->bitrate);
- g_mutex_lock(self->keyframe_mutex);
- param->force_i_frame = self->keyframe_event ? 1 : 0;
- if (self->keyframe_event) {
- gst_pad_push_event(base->srcpad, self->keyframe_event);
- self->keyframe_event = NULL;
- }
- g_mutex_unlock(self->keyframe_mutex);
- /* hack to manually force keyframes */
- if (!(self->mode == 1 && self->intra_refresh)) {
- param->force_i_frame |= self->force_i_frame_counter >=
- self->keyframe_interval * self->framerate;
- if (param->force_i_frame)
- self->force_i_frame_counter = 0;
- self->force_i_frame_counter++;
- }
- }
- static inline gboolean
- gst_dsp_set_codec_data_caps(GstDspBase *base,
- GstBuffer *buf)
- {
- GstCaps *caps = NULL;
- GstStructure *structure;
- GValue value = { .g_type = 0 };
- caps = gst_pad_get_negotiated_caps(base->srcpad);
- caps = gst_caps_make_writable(caps);
- structure = gst_caps_get_structure(caps, 0);
- g_value_init(&value, GST_TYPE_BUFFER);
- gst_value_set_buffer(&value, buf);
- gst_structure_set_value(structure, "codec_data", &value);
- g_value_unset(&value);
- return gst_pad_set_caps(base->srcpad, caps);
- }
- static inline void
- gst_dsp_h264venc_create_codec_data(GstDspBase *base)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- guint8 *sps, *pps, *codec_data;
- guint16 sps_size, pps_size, offset;
- sps = GST_BUFFER_DATA(self->priv.h264.sps);
- pps = GST_BUFFER_DATA(self->priv.h264.pps);
- sps_size = GST_BUFFER_SIZE(self->priv.h264.sps);
- pps_size = GST_BUFFER_SIZE(self->priv.h264.pps);
- offset = 0;
- self->priv.h264.codec_data = gst_buffer_new_and_alloc(sps_size + pps_size + 11);
- codec_data = GST_BUFFER_DATA(self->priv.h264.codec_data);
- codec_data[offset++] = 0x01;
- codec_data[offset++] = sps[1]; /* AVCProfileIndication*/
- codec_data[offset++] = sps[2]; /* profile_compatibility*/
- codec_data[offset++] = sps[3]; /* AVCLevelIndication */
- codec_data[offset++] = 0xff;
- codec_data[offset++] = 0xe1;
- codec_data[offset++] = (sps_size >> 8) & 0xff;
- codec_data[offset++] = sps_size & 0xff;
- memcpy(codec_data + offset, sps, sps_size);
- offset += sps_size;
- codec_data[offset++] = 0x1;
- codec_data[offset++] = (pps_size >> 8) & 0xff;
- codec_data[offset++] = pps_size & 0xff;
- memcpy(codec_data + offset, pps, pps_size);
- }
- static void
- h264venc_strip_sps_pps_header(GstDspBase *base,
- dmm_buffer_t *b,
- struct h264venc_out_stream_params *param)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- char *data = b->data;
- unsigned i;
- if (param->nalus_per_frame <= 1)
- return;
- if (!self->priv.h264.sps_received) {
- self->priv.h264.sps_received = TRUE;
- return;
- }
- for (i = 0; i < param->nalus_per_frame; i++) {
- if ((data[4] & 0x1f) == 7 || (data[4] & 0x1f) == 8) {
- data += param->nalu_sizes[i];
- b->data = data;
- b->len -= param->nalu_sizes[i];
- }
- }
- }
- static void
- h264venc_ignore_sps_pps_header(GstDspBase *base, dmm_buffer_t *b)
- {
- char *data = b->data;
- if ((data[4] & 0x1f) == 7 || (data[4] & 0x1f) == 8)
- base->skip_hack_2++;
- }
- static void
- h264venc_out_recv_cb(GstDspBase *base,
- du_port_t *port,
- dmm_buffer_t *p,
- dmm_buffer_t *b)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- struct h264venc_out_stream_params *param;
- param = p->data;
- pr_debug(base, "frame type: %d", param->frame_type);
- b->keyframe = (param->frame_type == 1 || param->frame_type == 4);
- if (b->len == 0)
- return;
- if (self->priv.h264.bytestream) {
- if (self->mode == 1)
- h264venc_strip_sps_pps_header(base, b, param);
- return;
- }
- if (G_LIKELY(self->priv.h264.codec_data_done)) {
- /* prefix the NALU with a lenght field, not counting the start code */
- *(uint32_t*)b->data = GINT_TO_BE(b->len - 4);
- if (self->mode == 1)
- h264venc_ignore_sps_pps_header(base, b);
- }
- else {
- if (!self->priv.h264.sps_received) {
- /* skip the start code 0x00000001 when storing SPS */
- self->priv.h264.sps = gst_buffer_new_and_alloc(b->len - 4);
- memcpy(GST_BUFFER_DATA(self->priv.h264.sps), b->data + 4, b->len - 4);
- self->priv.h264.sps_received = TRUE;
- } else if (!self->priv.h264.pps_received) {
- /* skip the start code 0x00000001 when storing PPS */
- self->priv.h264.pps = gst_buffer_new_and_alloc(b->len - 4);
- memcpy(GST_BUFFER_DATA(self->priv.h264.pps), b->data + 4, b->len - 4);
- self->priv.h264.pps_received = TRUE;
- }
- if (self->priv.h264.pps_received && self->priv.h264.sps_received) {
- gst_dsp_h264venc_create_codec_data(base);
- if (gst_dsp_set_codec_data_caps(base, self->priv.h264.codec_data)) {
- self->priv.h264.codec_data_done = TRUE;
- gst_buffer_replace(&self->priv.h264.sps, NULL);
- gst_buffer_replace(&self->priv.h264.pps, NULL);
- gst_buffer_replace(&self->priv.h264.codec_data, NULL);
- }
- }
- base->skip_hack_2++;
- }
- }
- static void
- setup_h264params_in(GstDspBase *base, dmm_buffer_t *tmp)
- {
- struct h264venc_in_stream_params *in_param;
- GstDspVEnc *self = GST_DSP_VENC(base);
- in_param = tmp->data;
- in_param->params_size = sizeof(*in_param);
- in_param->input_height = self->height;
- in_param->input_width = self->width;
- in_param->ref_framerate = self->framerate * 1000;
- in_param->target_framerate = self->framerate * 1000;
- in_param->target_bitrate = self->bitrate;
- in_param->qp_intra = 0x1c;
- in_param->qp_inter = 0x1c;
- in_param->qp_max = 0x33;
- in_param->max_mbs_per_slice = 3620;
- in_param->max_bytes_per_slice = 327680;
- in_param->max_mv_per_mb = 4;
- in_param->intra_4x4_enable_idc = 2;
- if (self->mode == 1 && self->intra_refresh) {
- unsigned pixels;
- /* Max delay in CBR, unit is is 1/30th of a second */
- in_param->intra_frame_interval = 0;
- /* For refreshing all the macroblocks in 3 sec */
- in_param->air_mb_period = self->framerate * 3;
- /* At least two intra macroblocks per frame */
- pixels = self->width * self->height;
- if (in_param->air_mb_period > pixels / (256 * 2))
- in_param->air_mb_period = pixels / (256 * 2);
- /*
- * Intra refresh methods:
- * 0 Doesn't insert forcefully intra macro blocks
- * 1 Inserts intra macro blocks in a cyclic fashion :
- * cyclic interval is equal to airMbPeriod
- * 3 Position of intra macro blocks is intelligently
- * chosen by encoder, but the number of forcely coded
- * intra macro blocks in a frame is guaranteed to be
- * equal to totalMbsInFrame/airMbPeriod
- */
- in_param->intra_refresh_method = 1;
- }
- }
- static inline void
- setup_h264params(GstDspBase *base)
- {
- struct h264venc_in_stream_params *in_param;
- struct h264venc_out_stream_params *out_param;
- du_port_t *p;
- p = base->ports[0];
- gstdsp_port_setup_params(base, p, sizeof(*in_param), setup_h264params_in);
- p->send_cb = h264venc_in_send_cb;
- p = base->ports[1];
- gstdsp_port_setup_params(base, p, sizeof(*out_param), NULL);
- p->recv_cb = h264venc_out_recv_cb;
- }
- struct jpegenc_in_stream_params {
- uint32_t size;
- };
- struct jpegenc_out_stream_params {
- uint32_t errorcode;
- };
- static void
- setup_jpegparams_in(GstDspBase *base, dmm_buffer_t *tmp)
- {
- struct jpegenc_in_stream_params *in_param;
- in_param = tmp->data;
- in_param->size = sizeof(*in_param);
- }
- static inline void
- setup_jpegparams(GstDspBase *base)
- {
- struct jpegenc_in_stream_params *in_param;
- struct jpegenc_out_stream_params *out_param;
- du_port_t *p;
- p = base->ports[0];
- gstdsp_port_setup_params(base, p, sizeof(*in_param), setup_jpegparams_in);
- p = base->ports[1];
- gstdsp_port_setup_params(base, p, sizeof(*out_param), NULL);
- }
- static void
- mp4venc_try_extract_codec_data(GstDspBase *base, dmm_buffer_t *b)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- guint8 gov[] = { 0x0, 0x0, 0x1, 0xB3 };
- guint8 vop[] = { 0x0, 0x0, 0x1, 0xB6 };
- guint8 *data;
- GstBuffer *codec_buf;
- if (G_LIKELY(self->priv.mpeg4.codec_data_done))
- return;
- if (!b->len)
- return;
- /* only mind codec-data for storage */
- if (self->mode)
- goto done;
- /*
- * Codec data expected in first frame,
- * and runs from VOSH to GOP (not including); so locate the latter one.
- */
- data = memmem(b->data, b->len, gov, 4);
- if (!data) {
- /* maybe no GOP is in the stream, look for first VOP */
- data = memmem(b->data, b->len, vop, 4);
- }
- if (!data) {
- pr_err(self, "failed to extract mpeg4 codec-data");
- goto done;
- }
- codec_buf = gst_buffer_new();
- GST_BUFFER_DATA(codec_buf) = b->data;
- GST_BUFFER_SIZE(codec_buf) = data - (guint8 *) b->data;
- gst_dsp_set_codec_data_caps(base, codec_buf);
- done:
- self->priv.mpeg4.codec_data_done = TRUE;
- }
- struct mp4venc_in_stream_params {
- uint32_t frame_index;
- uint32_t framerate;
- uint32_t bitrate;
- uint32_t i_frame_interval;
- uint32_t generate_header;
- uint32_t force_i_frame;
- uint32_t resync_interval;
- uint32_t hec_interval;
- uint32_t air_rate;
- uint32_t mir_rate;
- uint32_t qp_intra;
- uint32_t f_code;
- uint32_t half_pel;
- uint32_t ac_pred;
- uint32_t mv;
- uint32_t use_umv;
- uint32_t mv_data_enable;
- uint32_t resync_data_enable;
- uint32_t qp_inter;
- uint32_t last_frame;
- uint32_t width;
- /* SN_API >= 1 */
- uint32_t qp_max;
- uint32_t qp_min;
- };
- struct mp4venc_out_stream_params {
- uint32_t bitstream_size;
- uint32_t frame_type;
- uint32_t mv_data_size;
- uint32_t num_packets;
- uint8_t mv_data[12960];
- uint8_t resync_data[6480];
- /* SN_API >= 1 */
- uint32_t frame_index;
- uint32_t error_code;
- };
- static void
- mp4venc_out_recv_cb(GstDspBase *base,
- du_port_t *port,
- dmm_buffer_t *p,
- dmm_buffer_t *b)
- {
- struct mp4venc_out_stream_params *param;
- param = p->data;
- b->keyframe = (param->frame_type == 1);
- mp4venc_try_extract_codec_data(base, b);
- }
- static void
- mp4venc_in_send_cb(GstDspBase *base,
- du_port_t *port,
- dmm_buffer_t *p,
- dmm_buffer_t *b)
- {
- struct mp4venc_in_stream_params *param;
- GstDspVEnc *self = GST_DSP_VENC(base);
- param = p->data;
- param->frame_index = g_atomic_int_exchange_and_add(&self->frame_index, 1);
- param->bitrate = g_atomic_int_get(&self->bitrate);
- g_mutex_lock(self->keyframe_mutex);
- param->force_i_frame = self->keyframe_event ? 1 : 0;
- if (self->keyframe_event) {
- gst_pad_push_event(base->srcpad, self->keyframe_event);
- self->keyframe_event = NULL;
- }
- g_mutex_unlock(self->keyframe_mutex);
- }
- static void
- setup_mp4param_in(GstDspBase *base, dmm_buffer_t *tmp)
- {
- struct mp4venc_in_stream_params *in_param;
- GstDspVEnc *self = GST_DSP_VENC(base);
- in_param = tmp->data;
- in_param->framerate = self->framerate;
- in_param->bitrate = self->bitrate;
- in_param->i_frame_interval = self->keyframe_interval * self->framerate;
- in_param->air_rate = 10;
- in_param->qp_intra = 8;
- in_param->f_code = 6;
- in_param->half_pel = 1;
- in_param->qp_inter = 8;
- if (base->alg == GSTDSP_MP4VENC)
- in_param->ac_pred = 1;
- if (self->mode == 0) {
- in_param->use_umv = 1;
- } else {
- in_param->resync_interval = 1024;
- in_param->hec_interval = 3;
- }
- }
- static inline void
- setup_mp4params(GstDspBase *base)
- {
- struct mp4venc_in_stream_params *in_param;
- struct mp4venc_out_stream_params *out_param;
- du_port_t *p;
- p = base->ports[0];
- gstdsp_port_setup_params(base, p, sizeof(*in_param), setup_mp4param_in);
- p->send_cb = mp4venc_in_send_cb;
- p = base->ports[1];
- gstdsp_port_setup_params(base, p, sizeof(*out_param), NULL);
- p->recv_cb = mp4venc_out_recv_cb;
- }
- static void check_supported_levels(GstDspVEnc *self, GstCaps *caps)
- {
- GstDspBase *base = GST_DSP_BASE(self);
- GstCaps *allowed_caps;
- guint i;
- gint tgt_mbps, tgt_level, tgt_bitrate;
- struct gstdsp_codec_level *cur, *level;
- if (!self->supported_levels)
- return;
- tgt_level = -1;
- tgt_bitrate = self->user_max_bitrate;
- tgt_mbps = (self->width / 16 * self->height / 16) * self->framerate;
- /* see if downstream caps express something */
- allowed_caps = gst_pad_get_allowed_caps(base->srcpad);
- if (allowed_caps) {
- if (gst_caps_get_size(allowed_caps) > 0) {
- GstStructure *s;
- s = gst_caps_get_structure(allowed_caps, 0);
- gst_structure_get_int(s, "level", &tgt_level);
- }
- gst_caps_unref(allowed_caps);
- }
- search:
- level = cur = self->supported_levels;
- for (i = 0; i < self->nr_supported_levels; i++, cur++) {
- bool ok = false;
- /* is this the level we want? */
- if (tgt_level > 0 && tgt_level != cur->id)
- continue;
- /* is the bitrate enough? (and doesn't overshoot) */
- if (tgt_bitrate && cur->bitrate >= tgt_bitrate && level->bitrate < tgt_bitrate)
- ok = true;
- /* are the mbps enough? (and don't overshoot) */
- if (cur->mbps >= tgt_mbps && level->mbps < tgt_mbps)
- ok = true;
- /* at same level of mbps, get the biggest bitrate */
- if (cur->mbps >= tgt_mbps && cur->mbps == level->mbps &&
- !tgt_bitrate && cur->bitrate >= level->bitrate)
- ok = true;
- if (!ok)
- continue;
- /* we got a winner */
- level = cur;
- }
- if (tgt_level > 0 && tgt_level != level->id) {
- pr_warning(self, "invalid level: %d; ignoring", tgt_level);
- tgt_level = -1;
- goto search;
- }
- /* went beyond the table looking for a target; pick last one */
- if ((tgt_bitrate && level->bitrate < tgt_bitrate) || (level->mbps < tgt_mbps)) {
- if (tgt_level > 0) {
- pr_warning(self, "invalid level: %d; ignoring", tgt_level);
- tgt_level = -1;
- goto search;
- } else
- level = --cur;
- }
- if (!self->user_max_bitrate || self->user_max_bitrate >= level->bitrate)
- self->max_bitrate = level->bitrate;
- else
- self->max_bitrate = self->user_max_bitrate;
- pr_info(self, "level bitrate: %d", level->bitrate);
- pr_info(self, "max bitrate: %d", self->max_bitrate);
- pr_info(self, "level: %d", level->id);
- }
- static gboolean
- sink_setcaps(GstPad *pad,
- GstCaps *caps)
- {
- GstDspVEnc *self;
- GstDspBase *base;
- GstStructure *in_struc;
- GstCaps *out_caps;
- GstStructure *out_struc;
- gint width = 0, height = 0;
- self = GST_DSP_VENC(GST_PAD_PARENT(pad));
- base = GST_DSP_BASE(self);
- {
- gchar *str = gst_caps_to_string(caps);
- pr_info(self, "sink caps: %s", str);
- g_free(str);
- }
- in_struc = gst_caps_get_structure(caps, 0);
- out_caps = gst_caps_new_empty();
- switch (base->alg) {
- case GSTDSP_JPEGENC:
- out_struc = gst_structure_new("image/jpeg",
- NULL);
- break;
- case GSTDSP_H263ENC:
- out_struc = gst_structure_new("video/x-h263",
- "variant", G_TYPE_STRING, "itu",
- NULL);
- break;
- case GSTDSP_MP4VENC:
- out_struc = gst_structure_new("video/mpeg",
- "mpegversion", G_TYPE_INT, 4,
- "systemstream", G_TYPE_BOOLEAN, FALSE,
- NULL);
- break;
- case GSTDSP_H264ENC:
- out_struc = gst_structure_new("video/x-h264",
- NULL);
- break;
- default:
- return FALSE;
- }
- if (gst_structure_get_int(in_struc, "width", &width))
- gst_structure_set(out_struc, "width", G_TYPE_INT, width, NULL);
- if (gst_structure_get_int(in_struc, "height", &height))
- gst_structure_set(out_struc, "height", G_TYPE_INT, height, NULL);
- gst_structure_get_fourcc(in_struc, "format", &self->color_format);
- switch (base->alg) {
- case GSTDSP_H263ENC:
- case GSTDSP_MP4VENC:
- case GSTDSP_H264ENC:
- base->output_buffer_size = width * height / 2;
- break;
- case GSTDSP_JPEGENC:
- if (self->color_format == GST_MAKE_FOURCC('I', '4', '2', '0'))
- base->input_buffer_size = ROUND_UP(width, 16) * ROUND_UP(height, 16) * 3 / 2;
- else
- base->input_buffer_size = ROUND_UP(width, 16) * ROUND_UP(height, 16) * 2;
- base->output_buffer_size = width * height;
- self->quality = 90;
- if (self->quality < 10)
- base->output_buffer_size /= 10;
- else if (self->quality < 100)
- base->output_buffer_size /= (100 / self->quality);
- break;
- default:
- break;
- }
- switch (base->alg) {
- case GSTDSP_JPEGENC:
- du_port_alloc_buffers(base->ports[0], 1);
- du_port_alloc_buffers(base->ports[1], 1);
- break;
- default:
- du_port_alloc_buffers(base->ports[0], 2);
- du_port_alloc_buffers(base->ports[1], 2);
- break;
- }
- self->width = width;
- self->height = height;
- {
- const GValue *framerate = NULL;
- framerate = gst_structure_get_value(in_struc, "framerate");
- if (framerate) {
- gst_structure_set_value(out_struc, "framerate", framerate);
- /* calculate nearest integer */
- self->framerate = (gst_value_get_fraction_numerator(framerate) * 2 /
- gst_value_get_fraction_denominator(framerate) + 1) / 2;
- }
- }
- check_supported_levels(self, caps);
- if (self->bitrate == 0)
- self->bitrate = self->max_bitrate;
- else if (self->bitrate > self->max_bitrate)
- self->bitrate = self->max_bitrate;
- gst_caps_append_structure(out_caps, out_struc);
- {
- gchar *str = gst_caps_to_string(out_caps);
- pr_info(self, "src caps: %s", str);
- g_free(str);
- }
- if (!gst_pad_set_caps(base->srcpad, out_caps))
- return FALSE;
- base->node = create_node(self);
- if (!base->node) {
- pr_err(self, "dsp node creation failed");
- return FALSE;
- }
- /* setup stream params */
- switch (base->alg) {
- case GSTDSP_H263ENC:
- case GSTDSP_MP4VENC:
- setup_mp4params(base);
- break;
- case GSTDSP_H264ENC:
- setup_h264params(base);
- break;
- case GSTDSP_JPEGENC:
- setup_jpegparams(base);
- default:
- break;
- }
- if (!gstdsp_start(base)) {
- pr_err(self, "dsp start failed");
- return FALSE;
- }
- /* send dynamic params */
- switch (base->alg) {
- case GSTDSP_JPEGENC:
- jpegenc_send_params(base);
- break;
- default:
- break;
- }
- return TRUE;
- }
- static gboolean
- sink_event(GstDspBase *base,
- GstEvent *event)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- switch (GST_EVENT_TYPE(event)) {
- case GST_EVENT_CUSTOM_DOWNSTREAM:
- {
- const GstStructure *s;
- s = gst_event_get_structure(event);
- if (gst_structure_has_name(s, "GstForceKeyUnit")) {
- g_mutex_lock(self->keyframe_mutex);
- if (self->keyframe_event)
- gst_event_unref(self->keyframe_event);
- self->keyframe_event = event;
- g_mutex_unlock(self->keyframe_mutex);
- return TRUE;
- }
- break;
- }
- default:
- break;
- }
- if (parent_class->sink_event)
- return parent_class->sink_event(base, event);
- return gst_pad_push_event(base->srcpad, event);
- }
- static gboolean
- src_event(GstDspBase *base,
- GstEvent *event)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- switch (GST_EVENT_TYPE(event)) {
- case GST_EVENT_CUSTOM_UPSTREAM:
- {
- const GstStructure *s;
- s = gst_event_get_structure(event);
- if (gst_structure_has_name(s, "GstForceKeyUnit")) {
- g_mutex_lock(self->keyframe_mutex);
- /* make it downstream */
- GST_EVENT_TYPE(event) = GST_EVENT_CUSTOM_DOWNSTREAM;
- if (self->keyframe_event)
- gst_event_unref(self->keyframe_event);
- self->keyframe_event = event;
- g_mutex_unlock(self->keyframe_mutex);
- return TRUE;
- }
- break;
- }
- default:
- break;
- }
- if (parent_class->src_event)
- return parent_class->src_event(base, event);
- return gst_pad_push_event(base->sinkpad, event);
- }
- static void
- set_property(GObject *obj,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
- {
- GstDspVEnc *self = GST_DSP_VENC(obj);
- switch (prop_id) {
- case ARG_BITRATE: {
- guint bitrate;
- bitrate = g_value_get_uint(value);
- if (self->max_bitrate && bitrate > (unsigned) self->max_bitrate)
- bitrate = self->max_bitrate;
- g_atomic_int_set(&self->bitrate, g_value_get_uint(value));
- break;
- }
- case ARG_MODE:
- self->mode = g_value_get_enum(value);
- break;
- case ARG_KEYFRAME_INTERVAL:
- g_atomic_int_set(&self->keyframe_interval, g_value_get_int(value));
- break;
- case ARG_MAX_BITRATE:
- self->user_max_bitrate = g_value_get_uint(value);
- break;
- case ARG_INTRA_REFRESH:
- self->intra_refresh = g_value_get_boolean(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
- break;
- }
- }
- static void
- get_property(GObject *obj,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
- {
- GstDspVEnc *self = GST_DSP_VENC(obj);
- switch (prop_id) {
- case ARG_BITRATE:
- g_value_set_uint(value, g_atomic_int_get(&self->bitrate));
- break;
- case ARG_MODE:
- g_value_set_enum(value, self->mode);
- break;
- case ARG_KEYFRAME_INTERVAL:
- g_value_set_int(value, g_atomic_int_get(&self->keyframe_interval));
- break;
- case ARG_MAX_BITRATE: {
- guint bitrate;
- bitrate = self->user_max_bitrate;
- if (!bitrate)
- bitrate = self->max_bitrate;
- g_value_set_uint(value, bitrate);
- break;
- }
- case ARG_INTRA_REFRESH:
- g_value_set_boolean(value, self->intra_refresh);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, pspec);
- break;
- }
- }
- static void
- reset(GstDspBase *base)
- {
- GstDspVEnc *self = GST_DSP_VENC(base);
- pr_debug(self, "venc reset");
- /* some cleanup */
- if (base->alg == GSTDSP_H264ENC) {
- self->priv.h264.codec_data_done = FALSE;
- self->priv.h264.sps_received = FALSE;
- self->priv.h264.pps_received = FALSE;
- gst_buffer_replace(&self->priv.h264.sps, NULL);
- gst_buffer_replace(&self->priv.h264.pps, NULL);
- gst_buffer_replace(&self->priv.h264.codec_data, NULL);
- } else
- self->priv.mpeg4.codec_data_done = FALSE;
- }
- static void
- instance_init(GTypeInstance *instance,
- gpointer g_class)
- {
- GstDspBase *base = GST_DSP_BASE(instance);
- GstDspVEnc *self = GST_DSP_VENC(instance);
- gst_pad_set_setcaps_function(base->sinkpad, sink_setcaps);
- base->reset = reset;
- self->bitrate = DEFAULT_BITRATE;
- self->mode = DEFAULT_MODE;
- self->keyframe_interval = DEFAULT_KEYFRAME_INTERVAL;
- self->intra_refresh = DEFAULT_INTRA_REFRESH;
- self->keyframe_mutex = g_mutex_new();
- }
- static void
- finalize(GObject *obj)
- {
- GstDspVEnc *self = GST_DSP_VENC(obj);
- g_mutex_free(self->keyframe_mutex);
- if (self->keyframe_event)
- gst_event_unref(self->keyframe_event);
- G_OBJECT_CLASS(parent_class)->finalize(obj);
- }
- static void
- base_init(gpointer g_class)
- {
- GstElementClass *element_class;
- GstPadTemplate *template;
- element_class = GST_ELEMENT_CLASS(g_class);
- template = gst_pad_template_new("sink", GST_PAD_SINK,
- GST_PAD_ALWAYS,
- generate_sink_template());
- gst_element_class_add_pad_template(element_class, template);
- gst_object_unref(template);
- }
- static void
- class_init(gpointer g_class,
- gpointer class_data)
- {
- GObjectClass *gobject_class;
- GstDspBaseClass *base_class;
- parent_class = g_type_class_peek_parent(g_class);
- gobject_class = G_OBJECT_CLASS(g_class);
- base_class = GST_DSP_BASE_CLASS(g_class);
- gobject_class->set_property = set_property;
- gobject_class->get_property = get_property;
- g_object_class_install_property(gobject_class, ARG_BITRATE,
- g_param_spec_uint("bitrate", "Bit-rate",
- "Encoding bit-rate (0 for auto)",
- 0, G_MAXUINT, DEFAULT_BITRATE,
- G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, ARG_MODE,
- g_param_spec_enum("mode", "Encoding mode",
- "Encoding mode",
- GST_TYPE_DSPVENC_MODE,
- DEFAULT_MODE,
- G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, ARG_KEYFRAME_INTERVAL,
- g_param_spec_int("keyframe-interval", "Keyframe interval",
- "Generate keyframes at every specified intervals (seconds)",
- 0, G_MAXINT, DEFAULT_KEYFRAME_INTERVAL, G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, ARG_MAX_BITRATE,
- g_param_spec_uint("max-bitrate", "Maximum Bit-rate",
- "Maximum Encoding bit-rate (0 for auto)",
- 0, G_MAXUINT, DEFAULT_MAX_BITRATE,
- G_PARAM_READWRITE));
- g_object_class_install_property(gobject_class, ARG_INTRA_REFRESH,
- g_param_spec_boolean("intra-refresh", "Intra-refresh",
- "Whether or not to use periodic intra-refresh",
- DEFAULT_INTRA_REFRESH, G_PARAM_READWRITE));
- gobject_class->finalize = finalize;
- base_class->src_event = src_event;
- base_class->sink_event = sink_event;
- }
- GType
- gst_dsp_venc_get_type(void)
- {
- static GType type;
- if (G_UNLIKELY(type == 0)) {
- GTypeInfo type_info = {
- .class_size = sizeof(GstDspVEncClass),
- .class_init = class_init,
- .base_init = base_init,
- .instance_size = sizeof(GstDspVEnc),
- .instance_init = instance_init,
- };
- type = g_type_register_static(GST_DSP_BASE_TYPE, "GstDspVEnc", &type_info, 0);
- }
- return type;
- }
|