32 #include <libavformat/avformat.h> 33 #include <libavcodec/avcodec.h> 34 #include <libavutil/mathematics.h> 35 #include <libavutil/opt.h> 36 #include <libswscale/swscale.h> 37 #include <libmediaprocsutils/log.h> 38 #include <libmediaprocsutils/stat_codes.h> 39 #include <libmediaprocsutils/check_utils.h> 40 #include <libmediaprocsutils/fair_lock.h> 41 #include <libmediaprocsutils/fifo.h> 42 #include <libmediaprocs/proc_if.h> 43 #include <libmediaprocs/proc.h> 57 int ret_code, end_code= STAT_ERROR;
58 const AVCodec *avcodec= NULL;
59 AVCodecContext *avcodecctx= NULL;
60 AVDictionary *avdictionary= NULL;
61 LOG_CTX_INIT(log_ctx);
64 CHECK_DO(ffmpeg_video_enc_ctx!= NULL,
return STAT_ERROR);
65 CHECK_DO(video_settings_enc_ctx!= NULL,
return STAT_ERROR);
71 avcodec= avcodec_find_encoder((
enum AVCodecID)avcodecid);
73 LOGE(
"Video encoder not supported '%s'\n", avcodec_get_name(
74 (
enum AVCodecID)avcodecid));
75 end_code= STAT_EBAVFORMAT;
78 ffmpeg_video_enc_ctx->
avcodec= avcodec;
79 CHECK_DO(avcodec->type== AVMEDIA_TYPE_VIDEO,
goto end);
82 avcodecctx= avcodec_alloc_context3(avcodec);
83 CHECK_DO(avcodecctx!= NULL,
goto end);
87 avcodecctx->codec_id= avcodecid;
89 avcodecctx->framerate= (AVRational) {
97 avcodecctx->time_base= (AVRational)
99 avcodecctx->width= ffmpeg_video_enc_ctx->
width_input=
103 avcodecctx->gop_size= video_settings_enc_ctx->
gop_size;
106 if(strlen(video_settings_enc_ctx->
conf_preset)> 0) {
107 av_opt_set(avcodecctx->priv_data,
"preset",
115 ret_code= av_dict_copy(&avdictionary, ffmpeg_video_enc_ctx->
avdictionary,
129 avcodecctx->width, avcodecctx->height);
131 LOGE(
"Could not allocate temporal video raw frame.\n");
142 ffmpeg_video_enc_ctx->sws_ctx= NULL;
147 ret_code= avcodec_open2(ffmpeg_video_enc_ctx->
avcodecctx,
150 LOGE(
"Could not open video encoder: %s.\n", av_err2str(ret_code));
154 end_code= STAT_SUCCESS;
156 if(avdictionary!= NULL)
157 av_dict_free(&avdictionary);
158 if(end_code!= STAT_SUCCESS)
166 if(ffmpeg_video_enc_ctx== NULL)
170 avcodec_free_context(&ffmpeg_video_enc_ctx->
avcodecctx);
180 if(ffmpeg_video_enc_ctx->sws_ctx!= NULL) {
181 sws_freeContext(ffmpeg_video_enc_ctx->sws_ctx);
182 ffmpeg_video_enc_ctx->sws_ctx= NULL;
189 register int prev_pix_fmt_iput, pix_fmt_iput, pix_fmt_native_codec;
190 register int prev_width_iput, prev_height_iput, width_iput, height_iput,
191 width_codec_oput, height_codec_oput;
194 int ret_code, end_code= STAT_ERROR;
196 AVCodecContext *avcodecctx= NULL;
197 AVFrame *avframe_p= NULL;
198 AVFrame *avframe_tmp= NULL;
199 struct SwsContext *sws_ctx= NULL;
200 AVPacket pkt_oput= {0};
202 LOG_CTX_INIT(log_ctx);
205 CHECK_DO(ffmpeg_video_enc_ctx!= NULL,
return STAT_ERROR);
206 CHECK_DO(avframe_iput!= NULL,
return STAT_ERROR);
207 CHECK_DO(oput_fifo_ctx!= NULL,
return STAT_ERROR);
220 CHECK_DO(avcodecctx!= NULL,
goto end);
223 av_init_packet(&pkt_oput);
227 pix_fmt_iput= avframe_iput->format;
228 pix_fmt_native_codec= avcodecctx->pix_fmt;
231 prev_width_iput= ffmpeg_video_enc_ctx->
width_input;
233 width_iput= avframe_iput->width;
234 height_iput= avframe_iput->height;
235 width_codec_oput= avcodecctx->width;
236 height_codec_oput= avcodecctx->height;
242 avframe_p= avframe_iput;
249 if(prev_pix_fmt_iput!= pix_fmt_iput || prev_width_iput!= width_iput ||
250 prev_height_iput!= height_iput) {
253 if(pix_fmt_iput== AV_PIX_FMT_NONE) {
254 LOGE(
"Unknown or not supported input pixel format\n");
259 sws_ctx= sws_getContext(width_iput, height_iput, pix_fmt_iput,
260 width_codec_oput, height_codec_oput, AV_PIX_FMT_YUV420P,
261 SCALE_FLAGS, NULL, NULL, NULL);
263 if(ffmpeg_video_enc_ctx->sws_ctx!= NULL)
264 sws_freeContext(ffmpeg_video_enc_ctx->sws_ctx);
265 ffmpeg_video_enc_ctx->sws_ctx= sws_ctx;
277 if(pix_fmt_iput!= pix_fmt_native_codec || width_iput!= width_codec_oput ||
278 height_iput!= height_codec_oput) {
279 CHECK_DO(ffmpeg_video_enc_ctx->sws_ctx!= NULL,
goto end);
281 sws_scale(ffmpeg_video_enc_ctx->sws_ctx,
282 (
const uint8_t*
const*)avframe_p->data,
284 0, avframe_p->height,
288 ffmpeg_video_enc_ctx->
avframe_tmp->pts= avframe_iput->pts;
299 ret_code= avcodec_send_frame(avcodecctx, avframe_p);
303 while(ret_code>= 0 && proc_ctx->
flag_exit== 0) {
306 av_packet_unref(&pkt_oput);
307 ret_code= avcodec_receive_packet(avcodecctx, &pkt_oput);
308 if(ret_code== AVERROR(EAGAIN) || ret_code== AVERROR_EOF) {
309 end_code= STAT_EAGAIN;
327 pkt_oput.pos= avcodecctx->framerate.num;
330 if((flag_proc_features&PROC_FEATURE_LATENCY) &&
331 pkt_oput.pts!= AV_NOPTS_VALUE)
332 proc_stats_register_accumulated_latency(proc_ctx, pkt_oput.pts);
338 end_code= STAT_SUCCESS;
340 if(avframe_tmp!= NULL)
341 av_frame_free(&avframe_tmp);
343 sws_freeContext(sws_ctx);
344 av_packet_unref(&pkt_oput);
352 int ret_code, end_code= STAT_ERROR;
353 const AVCodec *avcodec= NULL;
354 AVCodecContext *avcodecctx= NULL;
355 LOG_CTX_INIT(log_ctx);
358 CHECK_DO(ffmpeg_video_dec_ctx!= NULL,
return STAT_ERROR);
359 CHECK_DO(video_settings_dec_ctx!= NULL,
return STAT_ERROR);
365 avcodec= avcodec_find_decoder((
enum AVCodecID)avcodecid);
367 LOGE(
"Video decoder not supported '%s'\n", avcodec_get_name(
368 (
enum AVCodecID)avcodecid));
369 end_code= STAT_EBAVFORMAT;
372 ffmpeg_video_dec_ctx->
avcodec= avcodec;
373 CHECK_DO(avcodec->type== AVMEDIA_TYPE_VIDEO,
goto end);
376 avcodecctx= avcodec_alloc_context3(avcodec);
377 CHECK_DO(avcodecctx!= NULL,
goto end);
381 avcodecctx->codec_id= avcodecid;
389 ret_code= avcodec_open2(ffmpeg_video_dec_ctx->
avcodecctx,
390 ffmpeg_video_dec_ctx->
avcodec, NULL);
392 LOGE(
"Could not open video decoder: %s.\n", av_err2str(ret_code));
396 end_code= STAT_SUCCESS;
398 if(end_code!= STAT_SUCCESS)
406 if(ffmpeg_video_dec_ctx== NULL)
410 avcodec_free_context(&ffmpeg_video_dec_ctx->
avcodecctx);
417 uint64_t flag_proc_features;
418 int ret_code, end_code= STAT_ERROR;
420 AVCodecContext *avcodecctx= NULL;
422 AVFrame *avframe_oput= NULL;
423 LOG_CTX_INIT(log_ctx);
426 CHECK_DO(ffmpeg_video_dec_ctx!= NULL,
return STAT_ERROR);
427 CHECK_DO(avpacket_iput!= NULL,
return STAT_ERROR);
428 CHECK_DO(oput_fifo_ctx!= NULL,
return STAT_ERROR);
441 CHECK_DO(avcodecctx!= NULL,
goto end);
450 ret_code= avcodec_send_packet(avcodecctx, avpacket_iput);
454 while(ret_code>= 0 && proc_ctx->
flag_exit== 0) {
455 if(avframe_oput!= NULL)
456 av_frame_free(&avframe_oput);
457 avframe_oput= av_frame_alloc();
458 CHECK_DO(avframe_oput!= NULL,
goto end);
459 ret_code= avcodec_receive_frame(avcodecctx, avframe_oput);
460 if(ret_code== AVERROR(EAGAIN) || ret_code== AVERROR_EOF) {
461 end_code= STAT_EAGAIN;
477 avframe_oput->sample_rate= avcodecctx->framerate.num;
480 if((flag_proc_features&PROC_FEATURE_LATENCY) &&
481 avframe_oput->pts!= AV_NOPTS_VALUE)
482 proc_stats_register_accumulated_latency(proc_ctx,
486 fifo_put_dup(oput_fifo_ctx, avframe_oput,
sizeof(
void*));
489 end_code= STAT_SUCCESS;
491 if(avframe_oput!= NULL)
492 av_frame_free(&avframe_oput);
497 volatile void *video_settings_opaque,
int flag_is_encoder,
500 int ret_code, flag_io_locked= 0, flag_thr_joined= 0;
501 void *thread_end_code= NULL;
502 AVDictionary *avdictionary= NULL;
503 LOG_CTX_INIT(log_ctx);
528 pthread_join(proc_ctx->
proc_thread, &thread_end_code);
529 if(thread_end_code!= NULL) {
530 ASSERT(*((
int*)thread_end_code)== STAT_SUCCESS);
531 free(thread_end_code);
532 thread_end_code= NULL;
542 if(flag_is_encoder!= 0) {
543 enum AVCodecID avcodecid;
544 AVCodecContext *avcodecctx= NULL;
552 CHECK_DO(avcodecctx!= NULL,
goto end);
553 avcodecid= avcodecctx->codec_id;
556 ret_code= av_dict_copy(&avdictionary,
564 ret_code= av_dict_copy(&ffmpeg_video_enc_ctx->
avdictionary,
569 (
int)avcodecid, video_settings_enc_ctx, LOG_CTX_GET());
570 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
572 enum AVCodecID avcodecid;
573 AVCodecContext *avcodecctx= NULL;
581 CHECK_DO(avcodecctx!= NULL,
goto end);
582 avcodecid= avcodecctx->codec_id;
586 (
int)avcodecid, video_settings_dec_ctx, LOG_CTX_GET());
587 CHECK_DO(ret_code== STAT_SUCCESS,
goto end);
596 if(flag_thr_joined!= 0) {
598 ret_code= pthread_create(&proc_ctx->
proc_thread, NULL,
604 if(flag_io_locked!= 0) {
609 if(avdictionary!= NULL)
610 av_dict_free(&avdictionary);
Facilities to convert processor's input/output frame to FFmpeg's formats and vice versa...
void ffmpeg_video_reset_on_new_settings(proc_ctx_t *proc_ctx, volatile void *video_settings_opaque, int flag_is_encoder, log_ctx_t *log_ctx)
Video encoder and decoder generic settings.
int fifo_put_dup(fifo_ctx_t *fifo_ctx, const void *elem, size_t elem_size)
void fifo_set_blocking_mode(fifo_ctx_t *fifo_ctx, int do_block)
int ffmpeg_video_enc_frame(ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx, AVFrame *avframe_iput, fifo_ctx_t *oput_fifo_ctx, log_ctx_t *log_ctx)
Generic processor module context (see type proc_ctx_t) extension for video encoders and decoders...
void fifo_empty(fifo_ctx_t *fifo_ctx)
AVFrame * allocate_frame_video(int pix_fmt, int width, int height)
uint64_t flag_proc_features
int ffmpeg_video_dec_frame(ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx, AVPacket *avpacket_iput, fifo_ctx_t *oput_fifo_ctx, log_ctx_t *log_ctx)
AVDictionary * avdictionary
const void *(* start_routine)(void *)
AVCodecContext * avcodecctx
void ffmpeg_video_dec_ctx_deinit(ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx, log_ctx_t *log_ctx)
#define CHECK_DO(COND, ACTION)
const proc_if_t * proc_if
fifo_ctx_t * fifo_ctx_array[PROC_IO_NUM]
int ffmpeg_video_enc_ctx_init(ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx, int avcodecid, const video_settings_enc_ctx_t *video_settings_enc_ctx, log_ctx_t *log_ctx)
AVCodecContext * avcodecctx
fair_lock_t * fair_lock_io_array[PROC_IO_NUM]
void ffmpeg_video_enc_ctx_deinit(ffmpeg_video_enc_ctx_t *ffmpeg_video_enc_ctx, log_ctx_t *log_ctx)
int ffmpeg_video_dec_ctx_init(ffmpeg_video_dec_ctx_t *ffmpeg_video_dec_ctx, int avcodecid, const video_settings_dec_ctx_t *video_settings_dec_ctx, log_ctx_t *log_ctx)