Skip to content

Commit

Permalink
Cleanup avformat-based preprocessors (meetecho#2665)
Browse files Browse the repository at this point in the history
  • Loading branch information
lu-zero committed May 27, 2021
1 parent 7b010cd commit 161fe7a
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 584 deletions.
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,8 @@ janus_pp_rec_SOURCES = \
postprocessing/pp-h264.h \
postprocessing/pp-av1.c \
postprocessing/pp-av1.h \
postprocessing/pp-avformat.c \
postprocessing/pp-avformat.h \
postprocessing/pp-h265.c \
postprocessing/pp-h265.h \
postprocessing/pp-opus.c \
Expand Down
150 changes: 20 additions & 130 deletions postprocessing/pp-av1.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,13 @@
#include <string.h>
#include <stdlib.h>

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

#include "pp-avformat.h"
#include "pp-av1.h"
#include "../debug.h"


#define LIBAVCODEC_VER_AT_LEAST(major, minor) \
(LIBAVCODEC_VERSION_MAJOR > major || \
(LIBAVCODEC_VERSION_MAJOR == major && \
LIBAVCODEC_VERSION_MINOR >= minor))

#if LIBAVCODEC_VER_AT_LEAST(51, 42)
#define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
#endif

#if LIBAVCODEC_VER_AT_LEAST(56, 56)
#ifndef CODEC_FLAG_GLOBAL_HEADER
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
#endif
#ifndef FF_INPUT_BUFFER_PADDING_SIZE
#define FF_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE
#endif
#endif

#if LIBAVCODEC_VER_AT_LEAST(57, 14)
#define USE_CODECPAR
#endif


/* MP4 output */
static AVFormatContext *fctx;
static AVStream *vStream;
#ifdef USE_CODECPAR
static AVCodecContext *vEncoder;
#endif
static uint16_t max_width = 0, max_height = 0;
int fps = 0;

Expand All @@ -65,98 +36,30 @@ int janus_pp_av1_create(char *destination, char *metadata, gboolean faststart) {
#if !LIBAVCODEC_VER_AT_LEAST(57, 25)
JANUS_LOG(LOG_ERR, "This version of libavcodec doesn't support AV1...\n");
return -1;
#endif
/* Setup FFmpeg */
#if ( LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) )
av_register_all();
#endif
/* Adjust logging to match the postprocessor's */
av_log_set_level(janus_log_level <= LOG_NONE ? AV_LOG_QUIET :
(janus_log_level == LOG_FATAL ? AV_LOG_FATAL :
(janus_log_level == LOG_ERR ? AV_LOG_ERROR :
(janus_log_level == LOG_WARN ? AV_LOG_WARNING :
(janus_log_level == LOG_INFO ? AV_LOG_INFO :
(janus_log_level == LOG_VERB ? AV_LOG_VERBOSE : AV_LOG_DEBUG))))));
#else
/* MP4 output */
fctx = avformat_alloc_context();
fctx = janus_pp_create_avformatcontext("mp4", metadata, destination);
if(fctx == NULL) {
JANUS_LOG(LOG_ERR, "Error allocating context\n");
return -1;
}
/* We save the metadata part as a comment (see #1189) */
if(metadata)
av_dict_set(&fctx->metadata, "comment", metadata, 0);
fctx->oformat = av_guess_format("mp4", NULL, NULL);
if(fctx->oformat == NULL) {
JANUS_LOG(LOG_ERR, "Error guessing format\n");
return -1;
}
char filename[1024];
snprintf(filename, sizeof(filename), "%s", destination);
#ifdef USE_CODECPAR
#if LIBAVCODEC_VER_AT_LEAST(57, 25)
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_AV1);
#else
if(!codec) {
/* Error opening video codec */
JANUS_LOG(LOG_ERR, "Encoder not available\n");
return -1;
}
#endif
fctx->video_codec = codec;
fctx->oformat->video_codec = codec->id;
vStream = avformat_new_stream(fctx, codec);
vStream->id = fctx->nb_streams-1;
vEncoder = avcodec_alloc_context3(codec);
vEncoder->width = max_width;
vEncoder->height = max_height;
vEncoder->time_base = (AVRational){ 1, fps };
vEncoder->pix_fmt = AV_PIX_FMT_YUV420P;
vEncoder->flags |= CODEC_FLAG_GLOBAL_HEADER;
vEncoder->strict_std_compliance = -2;
if(avcodec_open2(vEncoder, codec, NULL) < 0) {
/* Error opening video codec */
JANUS_LOG(LOG_ERR, "Encoder error\n");
return -1;
}
avcodec_parameters_from_context(vStream->codecpar, vEncoder);
#else
vStream = avformat_new_stream(fctx, 0);

vStream = janus_pp_new_video_avstream(fctx, AV_CODEC_ID_AV1, max_width, max_height);
if(vStream == NULL) {
JANUS_LOG(LOG_ERR, "Error adding stream\n");
return -1;
}
#if LIBAVCODEC_VER_AT_LEAST(53, 21)
avcodec_get_context_defaults3(vStream->codec, AVMEDIA_TYPE_VIDEO);
#else
avcodec_get_context_defaults2(vStream->codec, AVMEDIA_TYPE_VIDEO);
#endif
#if LIBAVCODEC_VER_AT_LEAST(57, 25)
vStream->codec->codec_id = AV_CODEC_ID_AV1;
#endif
vStream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
vStream->codec->time_base = (AVRational){1, fps};
vStream->time_base = (AVRational){1, 90000};
vStream->codec->width = max_width;
vStream->codec->height = max_height;
vStream->codec->pix_fmt = PIX_FMT_YUV420P;
//~ if (fctx->flags & AVFMT_GLOBALHEADER)
vStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
#endif

AVDictionary *options = NULL;
if(faststart)
av_dict_set(&options, "movflags", "+faststart", 0);

int res = avio_open2(&fctx->pb, filename, AVIO_FLAG_WRITE, NULL, &options);
if(res < 0) {
JANUS_LOG(LOG_ERR, "Error opening file for output (%d)\n", res);
return -1;
}
if(avformat_write_header(fctx, &options) < 0) {
JANUS_LOG(LOG_ERR, "Error writing header\n");
return -1;
}
return 0;
#endif
}

/* Helper to decode a leb128 integer */
Expand Down Expand Up @@ -422,6 +325,7 @@ int janus_pp_av1_process(FILE *file, janus_pp_frame_packet *list, int *working)
int len = 0, frameLen = 0, total = 0, dataLen = 0;
int keyFrame = 0;
gboolean keyframe_found = FALSE;
AVPacket *packet = av_packet_alloc();

while(*working && tmp != NULL) {
keyFrame = 0;
Expand Down Expand Up @@ -542,28 +446,28 @@ int janus_pp_av1_process(FILE *file, janus_pp_frame_packet *list, int *working)
total += frameLen;
JANUS_LOG(LOG_HUGE, "[%"SCNu64"] Saving frame: %d (tot=%d)\n", tmp->ts, frameLen, total);

AVPacket packet;
av_init_packet(&packet);
packet.stream_index = 0;
packet.data = received_frame;
packet.size = frameLen;
av_packet_unref(packet);
packet->stream_index = 0;
packet->data = received_frame;
packet->size = frameLen;
if(keyFrame)
packet.flags |= AV_PKT_FLAG_KEY;
packet->flags |= AV_PKT_FLAG_KEY;

/* First we save to the file... */
packet.dts = tmp->ts-list->ts;
packet.pts = tmp->ts-list->ts;
packet->dts = tmp->ts-list->ts;
packet->pts = tmp->ts-list->ts;
JANUS_LOG(LOG_HUGE, "%"SCNu64" - %"SCNu64" --> %"SCNu64"\n",
tmp->ts, list->ts, packet.pts);
tmp->ts, list->ts, packet->pts);
if(fctx) {
int res = av_write_frame(fctx, &packet);
int res = av_write_frame(fctx, packet);
if(res < 0) {
JANUS_LOG(LOG_ERR, "Error writing video frame to file... (error %d)\n", res);
}
}
}
tmp = tmp->next;
}
av_packet_free(&packet);
g_free(received_frame);
g_free(obu_data);
g_free(start);
Expand All @@ -572,23 +476,9 @@ int janus_pp_av1_process(FILE *file, janus_pp_frame_packet *list, int *working)

/* Close MP4 file */
void janus_pp_av1_close(void) {
if(fctx != NULL)
av_write_trailer(fctx);
#ifdef USE_CODECPAR
if(vEncoder != NULL)
avcodec_close(vEncoder);
#else
if(vStream != NULL && vStream->codec != NULL)
avcodec_close(vStream->codec);
#endif
if(fctx != NULL && fctx->streams[0] != NULL) {
#ifndef USE_CODECPAR
av_free(fctx->streams[0]->codec);
#endif
av_free(fctx->streams[0]);
}
if(fctx != NULL) {
av_write_trailer(fctx);
avio_close(fctx->pb);
av_free(fctx);
avformat_free_context(fctx);
}
}
92 changes: 92 additions & 0 deletions postprocessing/pp-avformat.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*! \file pp-avformat.c
* \copyright GNU General Public License v3
*
* \ingroup postprocessing
* \ref postprocessing
*/

#include "pp-avformat.h"

void janus_pp_setup_avformat(void) {
/* Setup FFmpeg */
#if ( LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58,9,100) )
av_register_all();
#endif
/* Adjust logging to match the postprocessor's */
av_log_set_level(janus_log_level <= LOG_NONE ? AV_LOG_QUIET :
(janus_log_level == LOG_FATAL ? AV_LOG_FATAL :
(janus_log_level == LOG_ERR ? AV_LOG_ERROR :
(janus_log_level == LOG_WARN ? AV_LOG_WARNING :
(janus_log_level == LOG_INFO ? AV_LOG_INFO :
(janus_log_level == LOG_VERB ? AV_LOG_VERBOSE : AV_LOG_DEBUG))))));

}

AVFormatContext *janus_pp_create_avformatcontext(const char *format, const char *metadata, const char *destination) {
janus_pp_setup_avformat();

AVFormatContext *ctx = avformat_alloc_context();
if(!ctx)
return NULL;

/* We save the metadata part as a comment (see #1189) */
if(metadata)
av_dict_set(&ctx->metadata, "comment", metadata, 0);

ctx->oformat = av_guess_format(format, NULL, NULL);
if(ctx->oformat == NULL) {
JANUS_LOG(LOG_ERR, "Error guessing format\n");
avformat_free_context(ctx);
return NULL;
}

int res = avio_open(&ctx->pb, destination, AVIO_FLAG_WRITE);
if(res < 0) {
JANUS_LOG(LOG_ERR, "Error opening file for output (%d)\n", res);
avformat_free_context(ctx);
return NULL;
}

return ctx;
}

AVStream *janus_pp_new_audio_avstream(AVFormatContext *fctx, int codec_id, int samplerate, int channels, const uint8_t *extradata, int size) {
AVStream *st = avformat_new_stream(fctx, NULL);
if(!st)
return NULL;

#ifdef USE_CODECPAR
AVCodecParameters *c = st->codecpar;
#else
AVCodecContext *c = st->codec;
#endif
c->codec_id = codec_id;
c->codec_type = AVMEDIA_TYPE_AUDIO;
c->sample_rate = samplerate;
c->channels = channels;
if(extradata) {
c->extradata_size = size;
c->extradata = av_memdup(extradata, size);
}

return st;
}

AVStream *janus_pp_new_video_avstream(AVFormatContext *fctx, int codec_id, int width, int height) {
AVStream *st = avformat_new_stream(fctx, NULL);
if(!st)
return NULL;

#ifdef USE_CODECPAR
AVCodecParameters *c = st->codecpar;
#else
AVCodecContext *c = st->codec;
#endif
c->codec_id = codec_id;
c->codec_type = AVMEDIA_TYPE_VIDEO;
c->width = width;
c->height = height;

return st;
}

46 changes: 46 additions & 0 deletions postprocessing/pp-avformat.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*! \file pp-avformat.h
* \copyright GNU General Public License v3
*
* \ingroup postprocessing
* \ref postprocessing
*/

#ifndef JANUS_PP_AVFORMAT
#define JANUS_PP_AVFORMAT

#include "../debug.h"

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>

#define LIBAVCODEC_VER_AT_LEAST(major, minor) \
(LIBAVCODEC_VERSION_MAJOR > major || \
(LIBAVCODEC_VERSION_MAJOR == major && \
LIBAVCODEC_VERSION_MINOR >= minor))

#if LIBAVCODEC_VER_AT_LEAST(51, 42)
#define PIX_FMT_YUV420P AV_PIX_FMT_YUV420P
#endif

#if LIBAVCODEC_VER_AT_LEAST(56, 56)
#ifndef CODEC_FLAG_GLOBAL_HEADER
#define CODEC_FLAG_GLOBAL_HEADER AV_CODEC_FLAG_GLOBAL_HEADER
#endif
#ifndef FF_INPUT_BUFFER_PADDING_SIZE
#define FF_INPUT_BUFFER_PADDING_SIZE AV_INPUT_BUFFER_PADDING_SIZE
#endif
#endif

#if LIBAVCODEC_VER_AT_LEAST(57, 14)
#define USE_CODECPAR
#endif

void janus_pp_setup_avformat(void);

AVFormatContext *janus_pp_create_avformatcontext(const char *format, const char *metadata, const char *destination);

AVStream *janus_pp_new_video_avstream(AVFormatContext *fctx, int codec_id, int width, int height);
AVStream *janus_pp_new_audio_avstream(AVFormatContext *fctx, int codec_id, int samplerate, int channels, const uint8_t *extradata, int size);


#endif
Loading

0 comments on commit 161fe7a

Please sign in to comment.