TT#30404 move portions required for decoding from recording-daemon to lib

Change-Id: I4170dd3c93ca3c87954d2c1db5fd84ae071247bd
changes/66/18566/10
Richard Fuchs 7 years ago
parent d510f5efe8
commit f8aad04948

1
daemon/.gitignore vendored

@ -8,3 +8,4 @@ auxlib.c
loglib.c
rtplib.c
codeclib.c
resample.c

@ -19,6 +19,11 @@ CFLAGS+= `pkg-config --cflags libiptc`
endif
CFLAGS+= -I. -I../kernel-module/ -I../lib/
CFLAGS+= -D_GNU_SOURCE
CFLAGS+= `pkg-config --cflags libavcodec`
CFLAGS+= `pkg-config --cflags libavformat`
CFLAGS+= `pkg-config --cflags libavutil`
CFLAGS+= `pkg-config --cflags libavresample`
CFLAGS+= `pkg-config --cflags libavfilter`
CFLAGS+= -DRE_PLUGIN_DIR="\"/usr/lib/rtpengine\""
@ -49,6 +54,11 @@ LDFLAGS+= `pkg-config --libs json-glib-1.0`
ifeq ($(with_iptables_option),yes)
LDFLAGS+= `pkg-config --libs libiptc`
endif
LDFLAGS+= `pkg-config --libs libavcodec`
LDFLAGS+= `pkg-config --libs libavformat`
LDFLAGS+= `pkg-config --libs libavutil`
LDFLAGS+= `pkg-config --libs libavresample`
LDFLAGS+= `pkg-config --libs libavfilter`
include ../lib/lib.Makefile
@ -57,7 +67,7 @@ SRCS= main.c kernel.c poller.c aux.c control_tcp.c streambuf.c call.c control_u
crypto.c rtp.c call_interfaces.c dtls.c log.c cli.c graphite.c ice.c socket.c \
media_socket.c homer.c recording.c statistics.c cdr.c ssrc.c iptables.c tcp_listener.c \
codec.c
LIBSRCS= loglib.c auxlib.c rtplib.c codeclib.c
LIBSRCS= loglib.c auxlib.c rtplib.c codeclib.c resample.c
OBJS= $(SRCS:.c=.o) $(LIBSRCS:.c=.o)

@ -162,6 +162,7 @@ enum call_type {
#define MEDIA_FLAG_ICE_LITE SHARED_FLAG_ICE_LITE
#define MEDIA_FLAG_ICE_CONTROLLING 0x00200000
#define MEDIA_FLAG_LOOP_CHECK 0x00400000
#define MEDIA_FLAG_TRANSCODE 0x00800000
/* access macros */
#define SP_ISSET(p, f) bf_isset(&(p)->sp_flags, SP_FLAG_ ## f)

@ -1,5 +1,6 @@
#include "codec.h"
#include <glib.h>
#include <assert.h>
#include "call.h"
#include "log.h"
#include "rtplib.h"
@ -9,6 +10,7 @@
static codec_handler_func handler_func_stub;
static codec_handler_func handler_func_transcode;
static struct codec_handler codec_handler_stub = {
@ -18,21 +20,53 @@ static struct codec_handler codec_handler_stub = {
static void __handler_shutdown(struct codec_handler *handler) {
if (handler->decoder)
decoder_close(handler->decoder);
handler->decoder = NULL;
}
static void __make_stub(struct codec_handler *handler) {
__handler_shutdown(handler);
handler->func = handler_func_stub;
}
static void __codec_handler_free(void *pp) {
struct codec_handler *h = pp;
__handler_shutdown(h);
g_slice_free1(sizeof(*h), h);
}
static void __make_transcoder(struct codec_handler *handler, struct rtp_payload_type *source,
struct rtp_payload_type *dest)
{
assert(source->codec_def != NULL);
assert(dest->codec_def != NULL);
__handler_shutdown(handler);
handler->func = handler_func_transcode;
handler->decoder = decoder_new_fmt(source->codec_def, source->clock_rate, 1, 0);
if (!handler->decoder)
goto err;
ilog(LOG_DEBUG, "Created transcode context for '" STR_FORMAT "' -> '" STR_FORMAT "'",
STR_FMT(&source->encoding), STR_FMT(&dest->encoding));
return;
err:
__make_stub(handler);
}
// call must be locked in W
void codec_handlers_update(struct call_media *receiver, struct call_media *sink) {
if (!receiver->codec_handlers)
receiver->codec_handlers = g_hash_table_new_full(g_int_hash, g_int_equal,
NULL, __codec_handler_free);
MEDIA_CLEAR(receiver, TRANSCODE);
// we go through the list of codecs that the receiver supports and compare it
// with the list of codecs supported by the sink. if the receiver supports
// a codec that the sink doesn't support, we must transcode.
@ -42,7 +76,10 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
struct rtp_payload_type *pref_dest_codec = NULL;
for (GList *l = sink->codecs_prefs_send.head; l; l = l->next) {
struct rtp_payload_type *pt = l->data;
// XXX if supported ...
if (!pt->codec_def)
pt->codec_def = codec_find(&pt->encoding);
if (!pt->codec_def) // not supported, next
continue;
ilog(LOG_DEBUG, "Default sink codec is " STR_FORMAT, STR_FMT(&pt->encoding));
pref_dest_codec = pt;
break;
@ -74,14 +111,16 @@ void codec_handlers_update(struct call_media *receiver, struct call_media *sink)
if (g_hash_table_lookup(sink->codec_names, &pt->encoding)) {
// the sink supports this codec. forward without transcoding.
// XXX check format parameters as well
ilog(LOG_DEBUG, "Sink supports codec " STR_FORMAT, STR_FMT(&pt->encoding));
__make_stub(handler);
continue;
}
// the sink does not support this codec XXX do something
// the sink does not support this codec -> transcode
ilog(LOG_DEBUG, "Sink does not support codec " STR_FORMAT, STR_FMT(&pt->encoding));
__make_stub(handler);
MEDIA_SET(receiver, TRANSCODE);
__make_transcoder(handler, pt, pref_dest_codec);
}
}
@ -122,6 +161,9 @@ static int handler_func_stub(struct codec_handler *h, struct call_media *media,
g_queue_push_tail(out, p);
return 0;
}
static int handler_func_transcode(struct codec_handler *h, struct call_media *media, const str *s, GQueue *out) {
return 0;
}
void codec_packet_free(void *pp) {
struct codec_packet *p = pp;

@ -4,6 +4,7 @@
#include <glib.h>
#include "str.h"
#include "codeclib.h"
struct call_media;
@ -16,6 +17,7 @@ typedef int codec_handler_func(struct codec_handler *, struct call_media *, cons
struct codec_handler {
int rtp_payload_type;
codec_handler_func *func;
decoder_t *decoder;
};
struct codec_packet {

@ -38,6 +38,7 @@
#include "iptables.h"
#include "statistics.h"
#include "graphite.h"
#include "codeclib.h"
@ -555,6 +556,7 @@ static void init_everything() {
if (call_interfaces_init())
abort();
statistics_init();
codeclib_init();
}

@ -0,0 +1,106 @@
import os
import ycm_core
from clang_helpers import PrepareClangFlags
# Set this to the absolute path to the folder (NOT the file!) containing the
# compile_commands.json file to use that instead of 'flags'. See here for
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
# Most projects will NOT need to set this to anything; you can just change the
# 'flags' list of compilation flags. Notice that YCM itself uses that approach.
compilation_database_folder = ''
# These are the compilation flags that will be used in case there's no
# compilation database set.
flags = [
'-g',
'-Wall',
'-pthread',
'-fno-strict-aliasing',
'-I/usr/include/glib-2.0',
'-I/usr/lib/x86_64-linux-gnu/glib-2.0/include',
'-pthread',
'-D_GNU_SOURCE',
'-D__DEBUG=1',
'-D__YCM=1',
'-DRTPENGINE_VERSION="dummy"',
'-DRE_PLUGIN_DIR="/usr/lib/rtpengine"',
'-DWITH_IPTABLES_OPTION',
'-O2',
'-fstack-protector',
'--param=ssp-buffer-size=4',
'-Wformat',
'-Werror=format-security',
'-D_FORTIFY_SOURCE=2',
# THIS IS IMPORTANT! Without a "-std=<something>" flag, clang won't
# know which language to use when compiling headers. So it will guess.
# Badly. So C++ headers will be compiled as C headers.
# You don't want that so ALWAYS specify
# a "-std=<something>".
# For a C project, you would set this to something like 'c99' instead of
# 'c++11'.
'-std=c99',
# ...and the same thing goes for the magic -x option which specifies the
# language that the files to be compiled are written in. This is mostly
# relevant for c++ headers.
# For a C project, you would set this to 'c' instead of 'c++'.
'-x',
'c',
]
if compilation_database_folder:
database = ycm_core.CompilationDatabase(compilation_database_folder)
else:
database = None
def DirectoryOfThisScript():
return os.path.dirname(os.path.abspath(__file__))
def MakeRelativePathsInFlagsAbsolute(flags, working_directory):
if not working_directory:
return flags
new_flags = []
make_next_absolute = False
path_flags = ['-isystem', '-I', '-iquote', '--sysroot=']
for flag in flags:
new_flag = flag
if make_next_absolute:
make_next_absolute = False
if not flag.startswith('/'):
new_flag = os.path.join(working_directory, flag)
for path_flag in path_flags:
if flag == path_flag:
make_next_absolute = True
break
if flag.startswith(path_flag):
path = flag[len(path_flag):]
new_flag = path_flag + os.path.join(working_directory, path)
break
if new_flag:
new_flags.append(new_flag)
return new_flags
def FlagsForFile(filename):
if database:
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info = database.GetCompilationInfoForFile(filename)
final_flags = PrepareClangFlags(
MakeRelativePathsInFlagsAbsolute(
compilation_info.compiler_flags_,
compilation_info.compiler_working_dir_),
filename)
else:
relative_to = DirectoryOfThisScript()
final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to)
return {
'flags': final_flags,
'do_cache': True
}

@ -1,7 +1,22 @@
#include "codeclib.h"
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <glib.h>
#include "str.h"
#include "log.h"
#include "resample.h"
#ifndef dbg
#ifdef __DEBUG
#define dbg(x...) ilog(LOG_DEBUG, x)
#else
#define dbg(x...) ((void)0)
#endif
#endif
@ -51,3 +66,203 @@ const codec_def_t *codec_find(const str *name) {
}
return NULL;
}
decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, int resample) {
const char *err = NULL;
clockrate *= def->clockrate_mult;
decoder_t *ret = g_slice_alloc0(sizeof(*ret));
format_init(&ret->in_format);
ret->in_format.channels = channels;
ret->in_format.clockrate = clockrate;
// output defaults to same as input
ret->out_format = ret->in_format;
if (resample)
ret->out_format.clockrate = resample;
// sample format to be determined later when decoded frames arrive
AVCodec *codec = NULL;
if (def->avcodec_name)
codec = avcodec_find_decoder_by_name(def->avcodec_name);
if (!codec)
codec = avcodec_find_decoder(def->avcodec_id);
if (!codec) {
ilog(LOG_WARN, "Codec '%s' not supported", def->rtpname);
goto err;
}
ret->avcctx = avcodec_alloc_context3(codec);
err = "failed to alloc codec context";
if (!ret->avcctx)
goto err;
ret->avcctx->channels = channels;
ret->avcctx->sample_rate = clockrate;
err = "failed to open codec context";
int i = avcodec_open2(ret->avcctx, codec, NULL);
if (i)
goto err;
for (const enum AVSampleFormat *sfmt = codec->sample_fmts; sfmt && *sfmt != -1; sfmt++)
dbg("supported sample format for input codec %s: %s",
codec->name, av_get_sample_fmt_name(*sfmt));
av_init_packet(&ret->avpkt);
ret->pts = (uint64_t) -1LL;
ret->rtp_ts = (unsigned long) -1L;
ret->mixer_idx = (unsigned int) -1;
return ret;
err:
decoder_close(ret);
if (err)
ilog(LOG_ERR, "Error creating media decoder: %s", err);
return NULL;
}
void decoder_close(decoder_t *dec) {
if (!dec)
return;
/// XXX drain inputs and outputs
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
avcodec_free_context(&dec->avcctx);
#else
avcodec_close(dec->avcctx);
av_free(dec->avcctx);
#endif
resample_shutdown(&dec->mix_resample);
resample_shutdown(&dec->output_resample);
g_slice_free1(sizeof(*dec), dec);
}
int decoder_input_data(decoder_t *dec, const str *data, unsigned long ts,
int (*callback)(decoder_t *, AVFrame *, void *u1, void *u2), void *u1, void *u2)
{
const char *err;
if (G_UNLIKELY(!dec))
return -1;
dbg("%p dec pts %llu rtp_ts %llu incoming ts %lu", dec, (unsigned long long) dec->pts,
(unsigned long long) dec->rtp_ts, (unsigned long) ts);
if (G_UNLIKELY(dec->rtp_ts == (unsigned long) -1L)) {
// initialize pts
dec->pts = 0;
}
else {
// shift pts according to rtp ts shift
dec->pts += (ts - dec->rtp_ts);
// XXX handle lost packets here if timestamps don't line up?
}
dec->rtp_ts = ts;
dec->avpkt.data = (unsigned char *) data->s;
dec->avpkt.size = data->len;
dec->avpkt.pts = dec->pts;
AVFrame *frame = NULL;
// loop until all input is consumed and all available output has been processed
int keep_going;
do {
keep_going = 0;
int got_frame = 0;
err = "failed to alloc av frame";
frame = av_frame_alloc();
if (!frame)
goto err;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 36, 0)
if (dec->avpkt.size) {
int ret = avcodec_send_packet(dec->avcctx, &dec->avpkt);
dbg("send packet ret %i", ret);
err = "failed to send packet to avcodec";
if (ret == 0) {
// consumed the packet
dec->avpkt.size = 0;
keep_going = 1;
}
else {
if (ret == AVERROR(EAGAIN))
; // try again after reading output
else
goto err;
}
}
int ret = avcodec_receive_frame(dec->avcctx, frame);
dbg("receive frame ret %i", ret);
err = "failed to receive frame from avcodec";
if (ret == 0) {
// got a frame
keep_going = 1;
got_frame = 1;
}
else {
if (ret == AVERROR(EAGAIN))
; // maybe needs more input now
else
goto err;
}
#else
// only do this if we have any input left
if (dec->avpkt.size == 0)
break;
int ret = avcodec_decode_audio4(dec->avcctx, frame, &got_frame, &dec->avpkt);
dbg("decode frame ret %i, got frame %i", ret, got_frame);
err = "failed to decode audio packet";
if (ret < 0)
goto err;
if (ret > 0) {
// consumed some input
err = "invalid return value";
if (ret > dec->avpkt.size)
goto err;
dec->avpkt.size -= ret;
dec->avpkt.data += ret;
keep_going = 1;
}
if (got_frame)
keep_going = 1;
#endif
if (got_frame) {
dbg("raw frame from decoder pts %llu samples %u", (unsigned long long) frame->pts, frame->nb_samples);
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 36, 0)
frame->pts = frame->pkt_pts;
#endif
if (G_UNLIKELY(frame->pts == AV_NOPTS_VALUE))
frame->pts = dec->avpkt.pts;
dec->avpkt.pts += frame->nb_samples;
if (callback(dec, frame, u1, u2))
return -1;
frame = NULL;
}
} while (keep_going);
av_frame_free(&frame);
return 0;
err:
ilog(LOG_ERR, "Error decoding media packet: %s", err);
av_frame_free(&frame);
return -1;
}
void codeclib_init() {
av_register_all();
avcodec_register_all();
avfilter_register_all();
avformat_network_init();
}

@ -2,20 +2,85 @@
#define __CODECLIB_H__
#include <libavresample/avresample.h>
#include <libavcodec/avcodec.h>
#include "str.h"
struct codec_def_s;
struct decoder_s;
struct format_s;
struct resample_s;
typedef struct codec_def_s codec_def_t;
typedef struct decoder_s decoder_t;
typedef struct format_s format_t;
typedef struct resample_s resample_t;
struct codec_def_s {
const char *rtpname;
int clockrate_mult;
int avcodec_id;
const char *avcodec_name;
};
typedef struct codec_def_s codec_def_t;
struct format_s {
int clockrate;
int channels;
int format; // enum AVSampleFormat
};
struct resample_s {
AVAudioResampleContext *avresample;
};
struct decoder_s {
format_t in_format,
out_format;
resample_t mix_resample,
output_resample;
AVCodecContext *avcctx;
AVPacket avpkt;
unsigned long rtp_ts;
uint64_t pts;
unsigned int mixer_idx;
};
void codeclib_init(void);
const codec_def_t *codec_find(const str *name);
decoder_t *decoder_new_fmt(const codec_def_t *def, int clockrate, int channels, int resample);
void decoder_close(decoder_t *dec);
int decoder_input_data(decoder_t *dec, const str *data, unsigned long ts,
int (*callback)(decoder_t *, AVFrame *, void *u1, void *u2), void *u1, void *u2);
INLINE int format_eq(const format_t *a, const format_t *b) {
if (G_UNLIKELY(a->clockrate != b->clockrate))
return 0;
if (G_UNLIKELY(a->channels != b->channels))
return 0;
if (G_UNLIKELY(a->format != b->format))
return 0;
return 1;
}
INLINE void format_init(format_t *f) {
f->clockrate = -1;
f->channels = -1;
f->format = -1;
}
#endif

@ -10,7 +10,7 @@
#include <libavutil/opt.h>
#include <libavutil/frame.h>
#include "log.h"
#include "types.h"
#include "codeclib.h"

@ -2,7 +2,7 @@
#define _RESAMPLE_H_
#include "types.h"
#include "codeclib.h"
#include <libavutil/frame.h>

@ -8,3 +8,4 @@ auxlib.c
loglib.c
rtplib.c
codeclib.c
resample.c

@ -25,8 +25,8 @@ LDFLAGS+= `mysql_config --libs`
include ../lib/lib.Makefile
SRCS= epoll.c garbage.c inotify.c main.c metafile.c stream.c recaux.c packet.c \
decoder.c output.c mix.c resample.c db.c log.c forward.c
LIBSRCS= loglib.c auxlib.c rtplib.c codeclib.c
decoder.c output.c mix.c db.c log.c forward.c
LIBSRCS= loglib.c auxlib.c rtplib.c codeclib.c resample.c
OBJS= $(SRCS:.c=.o) $(LIBSRCS:.c=.o)

@ -18,31 +18,11 @@
#include "codeclib.h"
struct decoder_s {
format_t in_format,
out_format;
resample_t mix_resample,
output_resample;
AVCodecContext *avcctx;
AVPacket avpkt;
unsigned long rtp_ts;
uint64_t pts;
unsigned int mixer_idx;
};
int resample_audio;
decoder_t *decoder_new(const char *payload_str) {
const char *err = NULL;
str name;
char *slash = strchr(payload_str, '/');
if (!slash) {
@ -68,58 +48,14 @@ decoder_t *decoder_new(const char *payload_str) {
}
clockrate *= def->clockrate_mult;
decoder_t *ret = g_slice_alloc0(sizeof(*ret));
format_init(&ret->in_format);
ret->in_format.channels = channels;
ret->in_format.clockrate = clockrate;
// output defaults to same as input
ret->out_format = ret->in_format;
if (resample_audio)
ret->out_format.clockrate = resample_audio;
// sample format to be determined later when decoded frames arrive
AVCodec *codec = NULL;
if (def->avcodec_name)
codec = avcodec_find_decoder_by_name(def->avcodec_name);
if (!codec)
codec = avcodec_find_decoder(def->avcodec_id);
if (!codec) {
ilog(LOG_WARN, "Codec '%s' not supported", def->rtpname);
goto err;
}
ret->avcctx = avcodec_alloc_context3(codec);
err = "failed to alloc codec context";
if (!ret->avcctx)
goto err;
ret->avcctx->channels = channels;
ret->avcctx->sample_rate = clockrate;
err = "failed to open codec context";
int i = avcodec_open2(ret->avcctx, codec, NULL);
if (i)
goto err;
for (const enum AVSampleFormat *sfmt = codec->sample_fmts; sfmt && *sfmt != -1; sfmt++)
dbg("supported sample format for input codec %s: %s", codec->name, av_get_sample_fmt_name(*sfmt));
av_init_packet(&ret->avpkt);
ret->pts = (uint64_t) -1LL;
ret->rtp_ts = (unsigned long) -1L;
ret->mixer_idx = (unsigned int) -1;
return ret;
err:
decoder_close(ret);
if (err)
ilog(LOG_ERR, "Error creating media decoder: %s", err);
return NULL;
return decoder_new_fmt(def, clockrate, channels, resample_audio);
}
static int decoder_got_frame(decoder_t *dec, output_t *output, metafile_t *metafile, AVFrame *frame) {
static int decoder_got_frame(decoder_t *dec, AVFrame *frame, void *op, void *mp) {
metafile_t *metafile = mp;
output_t *output = op;
dbg("got frame pts %llu samples %u contents %02x%02x%02x%02x...", (unsigned long long) frame->pts, frame->nb_samples,
(unsigned int) frame->extended_data[0][0],
(unsigned int) frame->extended_data[0][1],
@ -173,133 +109,5 @@ err:
int decoder_input(decoder_t *dec, const str *data, unsigned long ts, output_t *output, metafile_t *metafile) {
const char *err;
if (G_UNLIKELY(!dec))
return -1;
dbg("%p dec pts %llu rtp_ts %llu incoming ts %lu", dec, (unsigned long long) dec->pts,
(unsigned long long) dec->rtp_ts, (unsigned long) ts);
if (G_UNLIKELY(dec->rtp_ts == (unsigned long) -1L)) {
// initialize pts
dec->pts = 0;
}
else {
// shift pts according to rtp ts shift
dec->pts += (ts - dec->rtp_ts);
// XXX handle lost packets here if timestamps don't line up?
}
dec->rtp_ts = ts;
dec->avpkt.data = (unsigned char *) data->s;
dec->avpkt.size = data->len;
dec->avpkt.pts = dec->pts;
AVFrame *frame = NULL;
// loop until all input is consumed and all available output has been processed
int keep_going;
do {
keep_going = 0;
int got_frame = 0;
err = "failed to alloc av frame";
frame = av_frame_alloc();
if (!frame)
goto err;
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 36, 0)
if (dec->avpkt.size) {
int ret = avcodec_send_packet(dec->avcctx, &dec->avpkt);
dbg("send packet ret %i", ret);
err = "failed to send packet to avcodec";
if (ret == 0) {
// consumed the packet
dec->avpkt.size = 0;
keep_going = 1;
}
else {
if (ret == AVERROR(EAGAIN))
; // try again after reading output
else
goto err;
}
}
int ret = avcodec_receive_frame(dec->avcctx, frame);
dbg("receive frame ret %i", ret);
err = "failed to receive frame from avcodec";
if (ret == 0) {
// got a frame
keep_going = 1;
got_frame = 1;
}
else {
if (ret == AVERROR(EAGAIN))
; // maybe needs more input now
else
goto err;
}
#else
// only do this if we have any input left
if (dec->avpkt.size == 0)
break;
int ret = avcodec_decode_audio4(dec->avcctx, frame, &got_frame, &dec->avpkt);
dbg("decode frame ret %i, got frame %i", ret, got_frame);
err = "failed to decode audio packet";
if (ret < 0)
goto err;
if (ret > 0) {
// consumed some input
err = "invalid return value";
if (ret > dec->avpkt.size)
goto err;
dec->avpkt.size -= ret;
dec->avpkt.data += ret;
keep_going = 1;
}
if (got_frame)
keep_going = 1;
#endif
if (got_frame) {
dbg("raw frame from decoder pts %llu samples %u", (unsigned long long) frame->pts, frame->nb_samples);
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 36, 0)
frame->pts = frame->pkt_pts;
#endif
if (G_UNLIKELY(frame->pts == AV_NOPTS_VALUE))
frame->pts = dec->avpkt.pts;
dec->avpkt.pts += frame->nb_samples;
if (decoder_got_frame(dec, output, metafile, frame))
return -1;
frame = NULL;
}
} while (keep_going);
av_frame_free(&frame);
return 0;
err:
ilog(LOG_ERR, "Error decoding media packet: %s", err);
av_frame_free(&frame);
return -1;
}
void decoder_close(decoder_t *dec) {
if (!dec)
return;
/// XXX drain inputs and outputs
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 1, 0)
avcodec_free_context(&dec->avcctx);
#else
avcodec_close(dec->avcctx);
av_free(dec->avcctx);
#endif
resample_shutdown(&dec->mix_resample);
resample_shutdown(&dec->output_resample);
g_slice_free1(sizeof(*dec), dec);
return decoder_input_data(dec, data, ts, decoder_got_frame, output, metafile);
}

@ -10,7 +10,6 @@ extern int resample_audio;
decoder_t *decoder_new(const char *payload_str);
int decoder_input(decoder_t *, const str *, unsigned long ts, output_t *, metafile_t *);
void decoder_close(decoder_t *);
#endif

@ -23,6 +23,7 @@
#include "decoder.h"
#include "output.h"
#include "forward.h"
#include "codeclib.h"
@ -96,10 +97,7 @@ static void avlog_ilog(void *ptr, int loglevel, const char *fmt, va_list ap) {
static void setup(void) {
log_init("rtpengine-recording");
if (output_enabled) {
av_register_all();
avcodec_register_all();
avfilter_register_all();
avformat_network_init();
codeclib_init();
av_log_set_callback(avlog_ilog);
output_init(output_format);
if (!g_file_test(output_dir, G_FILE_TEST_IS_DIR)) {

@ -6,12 +6,12 @@
#include <sys/types.h>
#include <glib.h>
#include <libavutil/frame.h>
#include <libavresample/avresample.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
#include <libavutil/audio_fifo.h>
#include "str.h"
#include "codeclib.h"
struct iphdr;
@ -24,16 +24,10 @@ struct handler_s;
typedef struct handler_s handler_t;
struct metafile_s;
typedef struct metafile_s metafile_t;
struct decoder_s;
typedef struct decoder_s decoder_t;
struct output_s;
typedef struct output_s output_t;
struct mix_s;
typedef struct mix_s mix_t;
struct resample_s;
typedef struct resample_s resample_t;
struct format_s;
typedef struct format_s format_t;
typedef void handler_func(handler_t *);
@ -110,18 +104,6 @@ struct metafile_s {
};
struct resample_s {
AVAudioResampleContext *avresample;
};
struct format_s {
int clockrate;
int channels;
int format; // enum AVSampleFormat
};
struct output_s {
char full_filename[PATH_MAX], // path + filename
file_path[PATH_MAX],
@ -143,20 +125,5 @@ struct output_s {
};
INLINE int format_eq(const format_t *a, const format_t *b) {
if (G_UNLIKELY(a->clockrate != b->clockrate))
return 0;
if (G_UNLIKELY(a->channels != b->channels))
return 0;
if (G_UNLIKELY(a->format != b->format))
return 0;
return 1;
}
INLINE void format_init(format_t *f) {
f->clockrate = -1;
f->channels = -1;
f->format = -1;
}
#endif

Loading…
Cancel
Save