Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ XAV_VIDEO_CONVERTER_SO = $(PRIV_DIR)/libxavvideoconverter.so
# XAV_DEBUG_LOGS = -DXAV_DEBUG=1

DECODER_HEADERS = $(XAV_DIR)/xav_decoder.h $(XAV_DIR)/decoder.h $(XAV_DIR)/video_converter.h $(XAV_DIR)/audio_converter.h $(XAV_DIR)/utils.h $(XAV_DIR)/channel_layout.h
DECODER_SOURCES = $(XAV_DIR)/xav_decoder.c $(XAV_DIR)/decoder.c $(XAV_DIR)/video_converter.c $(XAV_DIR)/audio_converter.c $(XAV_DIR)/utils.c
DECODER_SOURCES = $(XAV_DIR)/xav_decoder.c $(XAV_DIR)/decoder.c $(XAV_DIR)/video_converter.c $(XAV_DIR)/audio_converter.c $(XAV_DIR)/utils.c $(XAV_DIR)/channel_layout.c

ENCODER_HEADERS = $(XAV_DIR)/xav_encoder.h $(XAV_DIR)/encoder.h $(XAV_DIR)/utils.h
ENCODER_SOURCES = $(XAV_DIR)/xav_encoder.c $(XAV_DIR)/encoder.c $(XAV_DIR)/utils.c
ENCODER_HEADERS = $(XAV_DIR)/xav_encoder.h $(XAV_DIR)/encoder.h $(XAV_DIR)/utils.h $(XAV_DIR)/channel_layout.h
ENCODER_SOURCES = $(XAV_DIR)/xav_encoder.c $(XAV_DIR)/encoder.c $(XAV_DIR)/utils.c $(XAV_DIR)/channel_layout.c

READER_HEADERS = $(XAV_DIR)/xav_reader.h $(XAV_DIR)/reader.h $(XAV_DIR)/video_converter.h $(XAV_DIR)/audio_converter.h $(XAV_DIR)/utils.h $(XAV_DIR)/channel_layout.h
READER_SOURCES = $(XAV_DIR)/xav_reader.c $(XAV_DIR)/reader.c $(XAV_DIR)/video_converter.c $(XAV_DIR)/audio_converter.c $(XAV_DIR)/utils.c
Expand Down
52 changes: 52 additions & 0 deletions c_src/xav/channel_layout.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include "channel_layout.h"

int xav_get_channel_layout(const char *name, struct ChannelLayout *layout) {
#if LIBAVUTIL_VERSION_MAJOR >= 58
if (av_channel_layout_from_string(&layout->layout, name) < 0) {
return 0;
}
#else
layout->layout = av_get_channel_layout(name);
if (layout->layout == 0) {
return 0;
}
#endif

return 1;
}

int xav_get_channel_layout_from_context(struct ChannelLayout *layout, const AVCodecContext *ctx) {
#if LIBAVUTIL_VERSION_MAJOR >= 58
return av_channel_layout_copy(&layout->layout, &ctx->ch_layout);
#else
layout->layout = ctx->channel_layout;
return 0;
#endif
}

int xav_set_channel_layout(AVCodecContext *ctx, struct ChannelLayout *layout) {
#if LIBAVUTIL_VERSION_MAJOR >= 58
return av_channel_layout_copy(&ctx->ch_layout, &layout->layout);
#else
ctx->channel_layout = layout->layout;
return 0;
#endif
}

int xav_set_default_channel_layout(struct ChannelLayout *layout, int channels) {
#if LIBAVUTIL_VERSION_MAJOR >= 58
av_channel_layout_default(&layout->layout, channels);
#else
layout->layout = av_get_default_channel_layout(channels);
#endif
return 0;
}

int xav_set_frame_channel_layout(AVFrame *frame, struct ChannelLayout *layout) {
#if LIBAVUTIL_VERSION_MAJOR >= 58
return av_channel_layout_copy(&frame->ch_layout, &layout->layout);
#else
frame->channel_layout = layout->layout;
return 0;
#endif
}
13 changes: 10 additions & 3 deletions c_src/xav/channel_layout.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#ifndef CHANNEL_LAYOUT_H
#define CHANNEL_LAYOUT_H
#ifndef XAV_CHANNEL_LAYOUT_H
#define XAV_CHANNEL_LAYOUT_H
#include <libavcodec/avcodec.h>
#include <libavutil/channel_layout.h>

struct ChannelLayout {
Expand All @@ -9,4 +10,10 @@ struct ChannelLayout {
uint64_t layout;
#endif
};
#endif

int xav_get_channel_layout(const char *name, struct ChannelLayout *layout);
int xav_get_channel_layout_from_context(struct ChannelLayout *layout, const AVCodecContext *ctx);
int xav_set_channel_layout(AVCodecContext *ctx, struct ChannelLayout *layout);
int xav_set_default_channel_layout(struct ChannelLayout *layout, int channels);
int xav_set_frame_channel_layout(AVFrame *frame, struct ChannelLayout *layout);
#endif
14 changes: 8 additions & 6 deletions c_src/xav/decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ struct Decoder *decoder_alloc() {
return decoder;
}

int decoder_init(struct Decoder *decoder, const AVCodec *codec) {
int decoder_init(struct Decoder *decoder, const AVCodec *codec, int channels) {
decoder->media_type = codec->type;
decoder->codec = codec;

Expand All @@ -22,6 +22,12 @@ int decoder_init(struct Decoder *decoder, const AVCodec *codec) {
return -1;
}

if (codec->type == AVMEDIA_TYPE_AUDIO && channels != -1) {
struct ChannelLayout ch_layout;
xav_set_default_channel_layout(&ch_layout, channels);
xav_set_channel_layout(decoder->c, &ch_layout);
}

decoder->frame = av_frame_alloc();
if (!decoder->frame) {
return -1;
Expand All @@ -32,11 +38,7 @@ int decoder_init(struct Decoder *decoder, const AVCodec *codec) {
return -1;
}

if (avcodec_open2(decoder->c, decoder->codec, NULL) < 0) {
return -1;
}

return 0;
return avcodec_open2(decoder->c, decoder->codec, NULL);
}

int decoder_decode(struct Decoder *decoder, AVPacket *pkt, AVFrame *frame) {
Expand Down
3 changes: 2 additions & 1 deletion c_src/xav/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <libswresample/swresample.h>

#include "audio_converter.h"
#include "channel_layout.h"
#include "utils.h"

#define MAX_FLUSH_BUFFER 16
Expand All @@ -16,7 +17,7 @@ struct Decoder {

struct Decoder *decoder_alloc();

int decoder_init(struct Decoder *decoder, const AVCodec *codec);
int decoder_init(struct Decoder *decoder, const AVCodec *codec, int channels);

int decoder_decode(struct Decoder *decoder, AVPacket *pkt, AVFrame *frame);

Expand Down
28 changes: 17 additions & 11 deletions c_src/xav/encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,27 @@ int encoder_init(struct Encoder *encoder, struct EncoderConfig *config) {
return -1;
}

encoder->c->width = config->width;
encoder->c->height = config->height;
encoder->c->pix_fmt = config->format;
encoder->c->time_base = config->time_base;
if (encoder->codec->type == AVMEDIA_TYPE_VIDEO) {
encoder->c->width = config->width;
encoder->c->height = config->height;
encoder->c->pix_fmt = config->format;
encoder->c->time_base = config->time_base;

if (config->profile != FF_PROFILE_UNKNOWN) {
encoder->c->profile = config->profile;
}
if (config->gop_size > 0) {
encoder->c->gop_size = config->gop_size;
}

if (config->gop_size > 0) {
encoder->c->gop_size = config->gop_size;
if (config->max_b_frames >= 0) {
encoder->c->max_b_frames = config->max_b_frames;
}
} else {
encoder->c->sample_fmt = config->sample_format;
encoder->c->sample_rate = config->sample_rate;
xav_set_channel_layout(encoder->c, &config->channel_layout);
}

if (config->max_b_frames >= 0) {
encoder->c->max_b_frames = config->max_b_frames;
if (config->profile != FF_PROFILE_UNKNOWN) {
encoder->c->profile = config->profile;
}

AVDictionary *opts = NULL;
Expand Down
4 changes: 4 additions & 0 deletions c_src/xav/encoder.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "channel_layout.h"
#include "utils.h"
#include <libavcodec/avcodec.h>

Expand All @@ -15,10 +16,13 @@ struct EncoderConfig {
int width;
int height;
enum AVPixelFormat format;
enum AVSampleFormat sample_format;
AVRational time_base;
int gop_size;
int max_b_frames;
int profile;
int sample_rate;
struct ChannelLayout channel_layout;
};

struct Encoder *encoder_alloc();
Expand Down
8 changes: 8 additions & 0 deletions c_src/xav/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,11 @@ ERL_NIF_TERM xav_nif_packet_to_term(ErlNifEnv *env, AVPacket *packet) {
enif_make_atom(env, packet->flags & AV_PKT_FLAG_KEY ? "true" : "false");
return enif_make_tuple(env, 4, data_term, dts, pts, is_keyframe);
}

int xav_get_nb_channels(const AVFrame *frame) {
#if LIBAVUTIL_VERSION_MAJOR >= 58
return frame->ch_layout.nb_channels;
#else
return frame->channels;
#endif
}
1 change: 1 addition & 0 deletions c_src/xav/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ ERL_NIF_TERM xav_nif_video_frame_to_term(ErlNifEnv *env, AVFrame *frame);
ERL_NIF_TERM xav_nif_audio_frame_to_term(ErlNifEnv *env, uint8_t **out_data, int out_samples,
int out_size, enum AVSampleFormat out_format, int pts);
ERL_NIF_TERM xav_nif_packet_to_term(ErlNifEnv *env, AVPacket *packet);
int xav_get_nb_channels(const AVFrame *frame);
38 changes: 18 additions & 20 deletions c_src/xav/xav_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@ void free_frames(AVFrame **frames, int size) {
}

ERL_NIF_TERM new (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
if (argc != 6) {
if (argc != 7) {
return xav_nif_raise(env, "invalid_arg_count");
}

ERL_NIF_TERM ret;
char *codec_name = NULL;
char *out_format = NULL;
int channels;

// resolve codec
if (!xav_nif_get_atom(env, argv[0], &codec_name)) {
Expand All @@ -37,8 +38,13 @@ ERL_NIF_TERM new (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
goto clean;
}

if (!enif_get_int(env, argv[1], &channels)) {
ret = xav_nif_raise(env, "failed_to_get_int");
goto clean;
}

// resolve output format
if (!xav_nif_get_atom(env, argv[1], &out_format)) {
if (!xav_nif_get_atom(env, argv[2], &out_format)) {
ret = xav_nif_raise(env, "failed_to_get_atom");
goto clean;
}
Expand All @@ -61,25 +67,25 @@ ERL_NIF_TERM new (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {

// resolve other params
int out_sample_rate;
if (!enif_get_int(env, argv[2], &out_sample_rate)) {
if (!enif_get_int(env, argv[3], &out_sample_rate)) {
ret = xav_nif_raise(env, "invalid_out_sample_rate");
goto clean;
}

int out_channels;
if (!enif_get_int(env, argv[3], &out_channels)) {
if (!enif_get_int(env, argv[4], &out_channels)) {
ret = xav_nif_raise(env, "invalid_out_channels");
goto clean;
}

int out_width;
if (!enif_get_int(env, argv[4], &out_width)) {
if (!enif_get_int(env, argv[5], &out_width)) {
ret = xav_nif_raise(env, "failed_to_get_int");
goto clean;
}

int out_height;
if (!enif_get_int(env, argv[5], &out_height)) {
if (!enif_get_int(env, argv[6], &out_height)) {
ret = xav_nif_raise(env, "failed_to_get_int");
goto clean;
}
Expand All @@ -102,7 +108,7 @@ ERL_NIF_TERM new (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
goto clean;
}

if (decoder_init(xav_decoder->decoder, codec) != 0) {
if (decoder_init(xav_decoder->decoder, codec, channels)) {
ret = xav_nif_raise(env, "failed_to_init_decoder");
goto clean;
}
Expand Down Expand Up @@ -341,21 +347,13 @@ static int init_audio_converter(struct XavDecoder *xav_decoder) {
}

struct ChannelLayout in_chlayout, out_chlayout;
#if LIBAVUTIL_VERSION_MAJOR >= 58
in_chlayout.layout = xav_decoder->decoder->c->ch_layout;
if (xav_decoder->out_channels == 0) {
out_chlayout.layout = in_chlayout.layout;
} else {
av_channel_layout_default(&out_chlayout.layout, xav_decoder->out_channels);
}
#else
in_chlayout.layout = xav_decoder->decoder->c->channel_layout;
xav_get_channel_layout_from_context(&in_chlayout, xav_decoder->decoder->c);

if (xav_decoder->out_channels == 0) {
out_chlayout.layout = in_chlayout.layout;
xav_get_channel_layout_from_context(&out_chlayout, xav_decoder->decoder->c);
} else {
out_chlayout.layout = av_get_default_channel_layout(xav_decoder->out_channels);
xav_set_default_channel_layout(&out_chlayout, xav_decoder->out_channels);
}
#endif

return audio_converter_init(xav_decoder->ac, in_chlayout, xav_decoder->decoder->c->sample_rate,
xav_decoder->decoder->c->sample_fmt, out_chlayout, out_sample_rate,
Expand Down Expand Up @@ -393,7 +391,7 @@ void free_xav_decoder(ErlNifEnv *env, void *obj) {
}
}

static ErlNifFunc xav_funcs[] = {{"new", 6, new},
static ErlNifFunc xav_funcs[] = {{"new", 7, new},
{"decode", 4, decode, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"flush", 1, flush, ERL_NIF_DIRTY_JOB_CPU_BOUND},
{"pixel_formats", 0, pixel_formats},
Expand Down
Loading
Loading