summaryrefslogtreecommitdiff
path: root/src/codec/ffmpeg
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec/ffmpeg')
-rw-r--r--src/codec/ffmpeg/decoder.c9
-rw-r--r--src/codec/ffmpeg/decoder.h4
-rw-r--r--src/codec/ffmpeg/demuxer.c35
-rw-r--r--src/codec/ffmpeg/packet_ext.c39
-rw-r--r--src/codec/ffmpeg/packet_ext.h1
-rw-r--r--src/codec/ffmpeg/scaler.c18
-rw-r--r--src/codec/ffmpeg/scaler.h2
7 files changed, 77 insertions, 31 deletions
diff --git a/src/codec/ffmpeg/decoder.c b/src/codec/ffmpeg/decoder.c
index d3ab3b2..0fb60ac 100644
--- a/src/codec/ffmpeg/decoder.c
+++ b/src/codec/ffmpeg/decoder.c
@@ -37,10 +37,11 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
}
s32 cpus = av_cpu_count();
- if (cpus > 4) cpus = 2;
+ if (cpus >= 8) cpus = 4;
av->codec_context->thread_count = cpus / 2;
// FF_THREAD_FRAME or FF_THREAD_SLICE.
- av->codec_context->thread_type = FF_THREAD_SLICE;
+ //av->codec_context->thread_type = FF_THREAD_SLICE;
+ av->codec_context->thread_type = FF_THREAD_FRAME;
al_log_debug("ff_decoder", "Using %i threads for decoder.", cpus);
#if !defined CAMU_SINK_NO_VIDEO && defined CAMU_RENDERER_VULKAN
@@ -61,8 +62,8 @@ static bool ff_decoder_init(struct camu_decoder *dec, struct camu_renderer *rend
s64 kbps = codecpar->bit_rate > 0 ? codecpar->bit_rate / 1000L : 0L;
al_log_info("ff_decoder", "Codec: %s (%s) %ldkbps.", codec->name, long_name, kbps);
- av->time_base = stream->av.stream->time_base;
- av->duration = stream->av.stream->duration;
+ //av->duration = stream->duration;
+ //av->time_base = stream->av.stream->time_base;
//av->last_pts = 0;
//av->last_duration = 0;
//av->seek_pos = -1;
diff --git a/src/codec/ffmpeg/decoder.h b/src/codec/ffmpeg/decoder.h
index 88bbd4c..2e35bb1 100644
--- a/src/codec/ffmpeg/decoder.h
+++ b/src/codec/ffmpeg/decoder.h
@@ -8,8 +8,8 @@
struct camu_ff_decoder {
struct camu_decoder dec;
AVCodecContext *codec_context;
- AVRational time_base;
- u64 duration;
+ //AVRational time_base;
+ //u64 duration;
//s64 last_pts;
//s64 last_duration;
//s64 seek_pos;
diff --git a/src/codec/ffmpeg/demuxer.c b/src/codec/ffmpeg/demuxer.c
index 8ea645b..24c1ba6 100644
--- a/src/codec/ffmpeg/demuxer.c
+++ b/src/codec/ffmpeg/demuxer.c
@@ -77,28 +77,31 @@ static bool ff_demuxer_init(struct camu_demuxer *demux, struct cch_handle *handl
for (u32 i = 0; i < av->format_context->nb_streams; i++) {
AVStream *stream = av->format_context->streams[i];
enum AVMediaType type = stream->codecpar->codec_type;
- if (type != AVMEDIA_TYPE_AUDIO && type != AVMEDIA_TYPE_VIDEO) type = AVMEDIA_TYPE_UNKNOWN;
- // Try to detect attached images.
- if (type == AVMEDIA_TYPE_VIDEO && GUESS_STREAM_IS_IMAGE(stream)) {
- al_log_info("ff_demuxer", "Guessing that stream #%u is an image.", i);
- stream->duration = 0;
- } else if (stream->duration < 0) {
- al_log_warn("ff_demuxer", "Stream #%u has an invalid duration (%ld).", i, stream->duration);
- if (av->format_context->duration < 0) {
- stream->duration = 0;
+ u64 duration = 0;
+ if (type == AVMEDIA_TYPE_AUDIO || type == AVMEDIA_TYPE_VIDEO || type == AVMEDIA_TYPE_SUBTITLE) {
+ // Try to detect attached images.
+ if (type == AVMEDIA_TYPE_VIDEO && GUESS_STREAM_IS_IMAGE(stream)) {
+ al_log_info("ff_demuxer", "Guessing that stream #%u is an image.", i);
} else {
- stream->duration = av_rescale_q(av->format_context->duration, AV_TIME_BASE_Q, stream->time_base);
+ if (stream->duration < 0) {
+ al_log_warn("ff_demuxer", "Stream #%u has an invalid duration (%ld).", i, stream->duration);
+ stream->duration = av->format_context->duration < 0 ? 0 :
+ av_rescale_q(av->format_context->duration, AV_TIME_BASE_Q, stream->time_base);
+ al_log_info("ff_demuxer", "Defaulting stream #%u to a duration of %.3fs.",
+ i, stream->duration * av_q2d(stream->time_base));
+ al_assert(stream->duration >= 0);
+ }
+ duration = (u64)av_rescale_q(stream->duration, stream->time_base, AV_TIME_BASE_Q);
+ if (duration > av->duration) av->duration = duration;
}
- al_log_info("ff_demuxer", "Setting stream #%u to a duration of %.3fs.", i, stream->duration * av_q2d(stream->time_base));
+ if (stream->start_time == AV_NOPTS_VALUE) stream->start_time = 0;
+ } else if (type != AVMEDIA_TYPE_ATTACHMENT) {
+ continue;
}
- if (stream->start_time == AV_NOPTS_VALUE) stream->start_time = 0;
- s64 duration = av_rescale_q(stream->duration, stream->time_base, AV_TIME_BASE_Q);
- al_assert(duration >= 0);
- if ((u64)duration > av->duration) av->duration = (u64)duration;
al_array_push(av->demux.streams, ((struct camu_codec_stream){
.mode = CAMU_FFMPEG_COMPAT,
.type = type,
- .duration = (u64)duration,
+ .duration = duration,
.av.stream = stream
}));
}
diff --git a/src/codec/ffmpeg/packet_ext.c b/src/codec/ffmpeg/packet_ext.c
index c0e400d..16f5748 100644
--- a/src/codec/ffmpeg/packet_ext.c
+++ b/src/codec/ffmpeg/packet_ext.c
@@ -38,6 +38,23 @@ void aki_packet_write_av_codec_id(struct aki_packet *packet, enum AVCodecID code
AKI_PACKET_WRITE_TYPE(packet, enum AVCodecID, codec_id);
}
+void aki_packet_write_av_dictionary(struct aki_packet *packet, AVDictionary *dict)
+{
+ s32 count = av_dict_count(dict);
+ AKI_PACKET_WRITE_TYPE(packet, s32, count);
+ const AVDictionaryEntry *entry = NULL;
+ while ((entry = av_dict_iterate(dict, entry))) {
+ size_t len = al_strlen(entry->key);
+ al_assert(len <= UINT32_MAX);
+ AKI_PACKET_WRITE_TYPE(packet, u32, len);
+ AKI_PACKET_WRITE_DATA(packet, entry->key, len);
+ len = al_strlen(entry->value);
+ al_assert(len <= UINT32_MAX);
+ AKI_PACKET_WRITE_TYPE(packet, u32, len);
+ AKI_PACKET_WRITE_DATA(packet, entry->value, len);
+ }
+}
+
void aki_packet_write_av_stream(struct aki_packet *packet, AVStream *stream)
{
AKI_PACKET_WRITE_TYPE(packet, s32, stream->index);
@@ -46,6 +63,7 @@ void aki_packet_write_av_stream(struct aki_packet *packet, AVStream *stream)
AKI_PACKET_WRITE_TYPE(packet, s64, stream->duration);
AKI_PACKET_WRITE_TYPE(packet, s64, stream->start_time);
AKI_PACKET_WRITE_TYPE(packet, s64, stream->nb_frames);
+ aki_packet_write_av_dictionary(packet, stream->metadata);
if (stream->avg_frame_rate.den == 0) {
// r_frame_rate.den == 0 handled on the client.
AKI_PACKET_WRITE_TYPE(packet, AVRational, stream->r_frame_rate);
@@ -118,6 +136,25 @@ enum AVCodecID aki_packet_read_av_codec_id(struct aki_packet *packet)
return id;
}
+void aki_packet_read_av_dictionary(struct aki_packet *packet, AVDictionary **dict)
+{
+ s32 count;
+ AKI_PACKET_READ_TYPE(packet, s32, count);
+ for (s32 i = 0; i < count; i++) {
+ char *key, *value;
+ u32 len;
+ AKI_PACKET_READ_TYPE(packet, u32, len);
+ AKI_PACKET_READ_DATA(packet, len, key);
+ // Key and value MUST be allocated with av_malloc functions
+ // just like all FFmpeg structures.
+ key = av_strndup(key, len);
+ AKI_PACKET_READ_TYPE(packet, u32, len);
+ AKI_PACKET_READ_DATA(packet, len, value);
+ value = av_strndup(value, len);
+ av_dict_set(dict, key, value, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
+ }
+}
+
AVStream *aki_packet_read_av_stream(AVFormatContext *format_context, const AVCodec *codec, struct aki_packet *packet)
{
AVStream *stream = avformat_new_stream(format_context, codec);
@@ -127,6 +164,8 @@ AVStream *aki_packet_read_av_stream(AVFormatContext *format_context, const AVCod
AKI_PACKET_READ_TYPE(packet, s64, stream->duration);
AKI_PACKET_READ_TYPE(packet, s64, stream->start_time);
AKI_PACKET_READ_TYPE(packet, s64, stream->nb_frames);
+ stream->metadata = NULL;
+ aki_packet_read_av_dictionary(packet, &stream->metadata);
AKI_PACKET_READ_TYPE(packet, AVRational, stream->avg_frame_rate);
return stream;
}
diff --git a/src/codec/ffmpeg/packet_ext.h b/src/codec/ffmpeg/packet_ext.h
index 36b6ed5..26a1392 100644
--- a/src/codec/ffmpeg/packet_ext.h
+++ b/src/codec/ffmpeg/packet_ext.h
@@ -6,6 +6,7 @@
#include <libavcodec/packet.h>
#include <libavcodec/codec_par.h>
#include <libavformat/avformat.h>
+#include <libavutil/dict.h>
void aki_packet_write_av_codec_parameters(struct aki_packet *packet, AVCodecParameters *codecpar);
void aki_packet_write_av_codec_id(struct aki_packet *packet, enum AVCodecID codec_id);
diff --git a/src/codec/ffmpeg/scaler.c b/src/codec/ffmpeg/scaler.c
index d233268..0089dd1 100644
--- a/src/codec/ffmpeg/scaler.c
+++ b/src/codec/ffmpeg/scaler.c
@@ -49,11 +49,12 @@ static bool ff_scaler_init(struct camu_scaler *scale, struct camu_scaler_format
return false;
}
- av->frame = alloc_picture(fmt->req.format, fmt->req.width, fmt->req.height);
- if (!av->frame) {
+ AVFrame *frame = alloc_picture(fmt->req.format, fmt->req.width, fmt->req.height);
+ if (!frame) {
al_log_error("ff_scaler", "Failed to allocate frame.");
return false;
}
+ av->frame.av.frame = frame;
return true;
}
@@ -61,8 +62,9 @@ static bool ff_scaler_init(struct camu_scaler *scale, struct camu_scaler_format
static bool ff_scaler_scale(struct camu_scaler *scale, const u8 **in_slice, s32 *in_strides)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)scale;
- s32 ret = sws_scale(av->scaler_context, in_slice, in_strides, 0, av->fmt.in.height,
- av->frame->data, av->frame->linesize);
+ AVFrame *frame = av->frame.av.frame;
+ s32 ret = sws_scale(av->scaler_context, in_slice, in_strides, 0,
+ av->fmt.in.height, frame->data, frame->linesize);
if (ret != av->fmt.req.height) {
al_log_error("ff_scaler", "Failed to scale frame (%s).", av_err2str(ret));
return false;
@@ -70,17 +72,17 @@ static bool ff_scaler_scale(struct camu_scaler *scale, const u8 **in_slice, s32
return true;
}
-static AVFrame *ff_scaler_get_frame(struct camu_scaler *scale)
+static struct camu_codec_frame *ff_scaler_get_frame(struct camu_scaler *scale)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)scale;
- return av->frame;
+ return &av->frame;
}
static void ff_scaler_free(struct camu_scaler **scale)
{
struct camu_ff_scaler *av = (struct camu_ff_scaler *)*scale;
- av_freep(&av->frame->data[0]);
- av_frame_free(&av->frame);
+ av_freep(&av->frame.av.frame->data[0]);
+ av_frame_free(&av->frame.av.frame);
sws_freeContext(av->scaler_context);
al_free(av);
*scale = NULL;
diff --git a/src/codec/ffmpeg/scaler.h b/src/codec/ffmpeg/scaler.h
index a4effb3..f01f3fd 100644
--- a/src/codec/ffmpeg/scaler.h
+++ b/src/codec/ffmpeg/scaler.h
@@ -9,7 +9,7 @@ struct camu_ff_scaler {
struct camu_scaler scale;
struct SwsContext *scaler_context;
struct camu_scaler_format fmt;
- AVFrame *frame;
+ struct camu_codec_frame frame;
};
struct camu_scaler *camu_ff_scaler_create(void);