diff --git a/lib/avc.c b/lib/avc.c index 047971a0b..0a73f7dfb 100644 --- a/lib/avc.c +++ b/lib/avc.c @@ -25,6 +25,16 @@ const codec_type_t codec_type_avcodec = { .encoder_close = avc_encoder_close, }; +const codec_type_t codec_type_video_avcodec = { + .def_init = avc_def_init, + .decoder_init = avc_video_decoder_init, + .decoder_input = avc_decoder_input, + .decoder_close = avc_decoder_close, + .encoder_init = avc_encoder_init, + .encoder_input = avc_encoder_input, + .encoder_close = avc_encoder_close, +}; + const char *avc_decoder_init(decoder_t *dec, const str *extra_opts) { const AVCodec *codec = dec->def->decoder; @@ -75,9 +85,20 @@ const char *avc_decoder_init(decoder_t *dec, const str *extra_opts) { } +const char *avc_video_decoder_init(decoder_t *dec, const str *extra_opts) { + dec->packet_buffer = g_string_sized_new(8192); + + return avc_decoder_init(dec, extra_opts); +} + + void avc_decoder_close(decoder_t *dec) { avcodec_free_context(&dec->avc.avcctx); av_packet_free(&dec->avc.avpkt); + if (dec->packet_buffer) { + g_string_free(dec->packet_buffer, true); + dec->packet_buffer = NULL; + } } @@ -365,6 +386,28 @@ int codeclib_set_av_opt_intstr(encoder_t *enc, const str *opt, const str *val) { } +void codeclib_avc_video_enc_options(str *key, str *value, void *encp) { + encoder_t *enc = encp; + + if (str_eq(key, "h")) + enc->actual_format.height = str_to_i(value, enc->actual_format.height); + else if (str_eq(key, "w")) + enc->actual_format.width = str_to_i(value, enc->actual_format.width); + else + codeclib_set_av_opt_intstr(enc, key, value); +} + + +int avc_video_encoder_input(encoder_t *enc, AVFrame **frame) { + int ret = avc_encoder_input(enc, frame); + if (ret < 0) + return ret; + if (enc->avpkt) + enc->next_pts = enc->avpkt->pts; + return ret; +} + + codec_def_t *codec_def_make_generic_av(enum AVCodecID id, enum media_type type) { { RWLOCK_R(&generic_ffmpeg_codecs_lock); diff --git a/lib/codeclib.c b/lib/codeclib.c index d04b0dd82..49eb22754 100644 --- a/lib/codeclib.c +++ b/lib/codeclib.c @@ -728,6 +728,7 @@ int encoder_config_fmtp(encoder_t *enc, codec_def_t *def, int bitrate, int ptime else ilog(LOG_DEBUG, "Initialized encoder without frame buffer"); + enc->frame_idx = ssl_random(); done: if (actual_format) @@ -784,7 +785,7 @@ static int encoder_input_direct(encoder_t *enc, AVFrame *frame, if (enc->avpkt->size) { // don't rely on the encoder producing steady timestamps, // instead keep track of them ourselves based on the returned - // frame duration + // frame duration (for audio) enc->avpkt->pts = enc->next_pts; if (enc->def->codec_type->encoder_got_packet) @@ -792,7 +793,7 @@ static int encoder_input_direct(encoder_t *enc, AVFrame *frame, callback(enc, u1, u2); - enc->next_pts += enc->avpkt->duration; + enc->next_pts += enc->avpkt->duration; // zero for video enc->mux_dts = enc->avpkt->dts + 1; // min next expected dts av_packet_unref(enc->avpkt); diff --git a/lib/codeclib.h b/lib/codeclib.h index f4be4c02e..f3e072bc0 100644 --- a/lib/codeclib.h +++ b/lib/codeclib.h @@ -321,6 +321,7 @@ struct decoder_s { resample_t resampler; rescale_t rescaler; + GString *packet_buffer; union { struct { @@ -350,6 +351,7 @@ struct decoder_s { }; unsigned long rtp_ts; + unsigned long dec_ts; uint64_t pts; int ptime; @@ -369,7 +371,11 @@ struct encoder_s { union codec_format_options format_options; resample_t resampler; - GString *sample_buffer; + + union { + GString *sample_buffer; + str_q nals; + }; union { struct { @@ -403,6 +409,7 @@ struct encoder_s { int64_t fifo_pts; // pts of first data in fifo int64_t packet_pts; // first pts of data in packetizer buffer int64_t next_pts; // next pts expected from the encoder + unsigned int frame_idx; int ptime; int bitrate; int samples_per_frame; // for encoding diff --git a/lib/codecmod.h b/lib/codecmod.h index 14dda8d40..18ec62e89 100644 --- a/lib/codecmod.h +++ b/lib/codecmod.h @@ -33,10 +33,14 @@ const char *avc_encoder_init(encoder_t *enc, const str *); int avc_encoder_input(encoder_t *enc, AVFrame **frame); void avc_encoder_close(encoder_t *enc); +const char *avc_video_decoder_init(decoder_t *, const str *); +int avc_video_encoder_input(encoder_t *enc, AVFrame **frame); + int codeclib_set_av_opt_int(encoder_t *enc, const char *opt, int64_t val); int codeclib_set_av_opt_intstr(encoder_t *enc, const str *opt, const str *val); void codeclib_key_value_parse(const str *instr, void (*cb)(str *key, str *value, void *data), void *data); +void codeclib_avc_video_enc_options(str *key, str *value, void *encp); void codeclib_register_codec(const codec_def_t *);