summaryrefslogtreecommitdiff
path: root/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/codec.h6
-rw-r--r--src/codec/libav/demuxer.c56
-rw-r--r--src/codec/libav/packet_ext.h1
-rw-r--r--src/codec/libav/scaler.c25
-rw-r--r--src/codec/meson.build17
-rw-r--r--src/codec/stb_image/impl.c2
6 files changed, 55 insertions, 52 deletions
diff --git a/src/codec/codec.h b/src/codec/codec.h
index d30a648..1309210 100644
--- a/src/codec/codec.h
+++ b/src/codec/codec.h
@@ -61,8 +61,7 @@ struct camu_stream {
s32 height;
struct camu_icc_profile icc;
} video;
- //struct {
- //} audio;
+ //struct { } audio;
#ifdef HAVE_FFMPEG
struct {
AVStream *stream;
@@ -94,13 +93,14 @@ struct camu_frame {
};
struct camu_demuxer {
+ u8 type;
bool (*init)(struct camu_demuxer *, struct cch_handle *);
s32 (*get_packet)(struct camu_demuxer *, struct camu_packet *);
s64 (*get_duration)(struct camu_demuxer *);
bool (*seek)(struct camu_demuxer *, s64);
void (*free)(struct camu_demuxer **);
- u8 type;
array(struct camu_stream) streams;
+ array(s32) subscribed;
};
struct camu_renderer;
diff --git a/src/codec/libav/demuxer.c b/src/codec/libav/demuxer.c
index f7ff35c..d823d23 100644
--- a/src/codec/libav/demuxer.c
+++ b/src/codec/libav/demuxer.c
@@ -65,47 +65,30 @@ static bool lav_demuxer_init(struct camu_demuxer *demux, struct cch_handle *hand
av->duration = 0;
- bool audio_selected = false;
- bool video_selected = false;
+#define GUESS_STREAM_IS_IMAGE(stream) \
+ (stream->duration >= 0 && stream->nb_frames <= 1 && (stream->avg_frame_rate.den == 0 && stream->r_frame_rate.den > 0))
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)) {
- continue;
- }
- if (type == AVMEDIA_TYPE_AUDIO) {
- if (audio_selected) continue;
- else audio_selected = true;
- }
- if (type == AVMEDIA_TYPE_VIDEO) {
- if (video_selected) continue;
- else video_selected = true;
- }
// Try to detect attached images.
- if (type == AVMEDIA_TYPE_VIDEO && stream->duration >= 0 && stream->nb_frames <= 1 &&
- (stream->avg_frame_rate.den == 0 && stream->r_frame_rate.den > 0)) {
- stream->duration = 0;
+ if (type == AVMEDIA_TYPE_VIDEO && GUESS_STREAM_IS_IMAGE(stream)) {
al_log_info("lav_demux", "Assuming stream #%i is an image.", i);
+ stream->duration = 0;
} else if (stream->duration < 0) {
+ al_log_warn("lav_demux", "Stream #%i has invalid duration (%ld).", av->format_context->duration);
if (av->format_context->duration < 0) {
stream->duration = 0;
} else {
- // This could be completely wrong. In that case, it's still probably
- // better than 0 (assuming the stream is not an image).
- stream->duration = av_rescale_q(av->format_context->duration,
- AV_TIME_BASE_Q, stream->time_base);
+ stream->duration = av_rescale_q(av->format_context->duration, AV_TIME_BASE_Q, stream->time_base);
}
- al_log_info("lav_demux", "Setting stream #%i to a duration of %.3fs.",
- i, stream->duration * av_q2d(stream->time_base));
+ al_log_info("lav_demux", "Setting stream #%i to a duration of %.3fs.", i, stream->duration * av_q2d(stream->time_base));
}
if (stream->start_time < 0) {
- stream->start_time = 0;
+ al_log_warn("lav_demux", "Stream has a negative start_time (%ld).", stream->start_time);
}
s64 duration = av_rescale_q(stream->duration, stream->time_base, AV_TIME_BASE_Q);
- if (duration > av->duration) {
- av->duration = duration;
- }
+ if (duration > av->duration) av->duration = duration;
al_array_push(av->demux.streams, ((struct camu_stream){
.type = CAMU_FFMPEG_COMPAT,
.av.stream = stream
@@ -125,6 +108,15 @@ err:
return false;
}
+static bool subscribed_to_index(struct camu_demuxer *demux, s32 index)
+{
+ s32 subscribed;
+ al_array_foreach(demux->subscribed, i, subscribed) {
+ if (subscribed == index) return true;
+ }
+ return false;
+}
+
static s32 lav_demuxer_get_packet(struct camu_demuxer *demux, struct camu_packet *packet)
{
struct camu_lav_demuxer *av = (struct camu_lav_demuxer *)demux;
@@ -132,12 +124,19 @@ static s32 lav_demuxer_get_packet(struct camu_demuxer *demux, struct camu_packet
s32 ret = 0;
do {
ret = av_read_frame(av->format_context, packet->av.pkt);
- if (ret < 0 && ret != AVERROR_EOF) {
+ if (ret == AVERROR_EOF) {
+ av->eof = true;
+ break;
+ }
+ if (ret < 0) {
al_log_error("lav_demuxer", "Failed to read frame (%s).", av_err2str(ret));
}
+ if (!subscribed_to_index(demux, packet->av.pkt->stream_index)) {
+ av_packet_unref(packet->av.pkt);
+ continue;
+ }
break;
} while (1);
- if (ret == AVERROR_EOF) av->eof = true;
return ret;
}
@@ -175,6 +174,7 @@ struct camu_demuxer *camu_lav_demuxer_create(void)
struct camu_lav_demuxer *av = al_alloc_object(struct camu_lav_demuxer);
av->demux.type = CAMU_FFMPEG_COMPAT;
al_array_init(av->demux.streams);
+ al_array_init(av->demux.subscribed);
av->demux.init = lav_demuxer_init;
av->demux.get_packet = lav_demuxer_get_packet;
av->demux.get_duration = lav_demuxer_get_duration;
diff --git a/src/codec/libav/packet_ext.h b/src/codec/libav/packet_ext.h
index e2f7cd5..ff6e337 100644
--- a/src/codec/libav/packet_ext.h
+++ b/src/codec/libav/packet_ext.h
@@ -1,6 +1,7 @@
#pragma once
#include <aki/common.h>
+#include <aki/event_loop.h>
#include <libavcodec/packet.h>
#include <libavcodec/codec_par.h>
diff --git a/src/codec/libav/scaler.c b/src/codec/libav/scaler.c
index 6146c69..882116f 100644
--- a/src/codec/libav/scaler.c
+++ b/src/codec/libav/scaler.c
@@ -9,6 +9,12 @@ static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, s32 width, s32 height)
{
AVFrame *frame = av_frame_alloc();
if (!frame) return NULL;
+ s32 ret = av_image_alloc(frame->data, frame->linesize, width, height, pix_fmt, 32);
+ if (ret < 0) {
+ al_log_error("lav_scaler", "Failed to allocate picture buffer (%s).", av_err2str(ret));
+ return NULL;
+ }
+ /*
s32 size = av_image_get_buffer_size(pix_fmt, width, height, 1);
u8 *buffer = (u8 *)av_malloc(size);
if (!buffer) {
@@ -21,6 +27,7 @@ static AVFrame *alloc_picture(enum AVPixelFormat pix_fmt, s32 width, s32 height)
av_free(frame);
return NULL;
}
+ */
frame->width = width;
frame->height = height;
frame->format = pix_fmt;
@@ -31,32 +38,28 @@ bool camu_lav_scaler_init(struct camu_lav_scaler *scale, struct camu_lav_scale_f
{
al_memset(scale, 0, sizeof(struct camu_lav_scaler));
- /*
if (fmt->in_width == fmt->req_width && fmt->in_height == fmt->req_height &&
fmt->in_format == fmt->req_format) {
fmt->scaler_needed = false;
return true;
}
- */
-
- fmt->scaler_needed = true;
+ s32 flags = SWS_BITEXACT;
scale->scaler_context = sws_getContext(fmt->in_width, fmt->in_height, fmt->in_format,
- fmt->req_width, fmt->req_height, fmt->req_format,
- SWS_BITEXACT, NULL, NULL, NULL);
-
+ fmt->req_width, fmt->req_height, fmt->req_format, flags, NULL, NULL, NULL);
if (!scale->scaler_context) {
al_log_error("lav_scaler", "Failed to create scaler context.");
return false;
}
scale->frame = alloc_picture(fmt->req_format, fmt->req_width, fmt->req_height);
-
if (!scale->frame) {
al_log_error("lav_scaler", "Failed to allocate frame.");
return false;
}
+ fmt->scaler_needed = true;
+
scale->fmt = *fmt;
return true;
@@ -64,8 +67,8 @@ bool camu_lav_scaler_init(struct camu_lav_scaler *scale, struct camu_lav_scale_f
bool camu_lav_scaler_scale(struct camu_lav_scaler *scale, const u8 **in_slice, s32 *in_strides)
{
- s32 ret = sws_scale(scale->scaler_context, in_slice, in_strides, 0,
- scale->fmt.in_height, scale->frame->data, scale->frame->linesize);
+ s32 ret = sws_scale(scale->scaler_context, in_slice, in_strides, 0, scale->fmt.in_height,
+ scale->frame->data, scale->frame->linesize);
if (ret != scale->fmt.req_height) {
al_log_error("lav_scaler", "Failed to scale frame (%s).", av_err2str(ret));
return false;
@@ -75,5 +78,7 @@ bool camu_lav_scaler_scale(struct camu_lav_scaler *scale, const u8 **in_slice, s
void camu_lav_scaler_close(struct camu_lav_scaler *scale)
{
+ av_freep(&scale->frame->data[0]);
+ av_frame_free(&scale->frame);
sws_freeContext(scale->scaler_context);
}
diff --git a/src/codec/meson.build b/src/codec/meson.build
index e1fd5f7..b4472fb 100644
--- a/src/codec/meson.build
+++ b/src/codec/meson.build
@@ -54,14 +54,11 @@ if libavutil.found() and libavformat.found() and libavcodec.found() and libswres
add_project_arguments('-DHAVE_FFMPEG', language: ['c', 'cpp'])
endif
-stb_image = subproject('stb_image').get_variable('stb_image')
-#stb_image_decoder = declare_dependency(sources: ['stb_image/impl.c'],
-# dependencies: stb_image)
-#
-wuffs = subproject('wuffs').get_variable('wuffs')
-wuffs_decoder = declare_dependency(sources: ['wuffs/impl.c'],
- dependencies: wuffs)
+stb_image = declare_dependency(sources: ['stb_image/impl.c'],
+ dependencies: subproject('stb').get_variable('stb'))
-#spng = dependency('spng')
-#spng_decoder = declare_dependency(sources: ['spng/impl.c'],
-# dependencies: spng)
+#wuffs = declare_dependency(sources: ['wuffs/impl.c'],
+# dependencies: subproject('wuffs').get_variable('wuffs'))
+
+#spng = declare_dependency(sources: ['spng/impl.c'],
+# dependencies: dependency('spng'))
diff --git a/src/codec/stb_image/impl.c b/src/codec/stb_image/impl.c
index 953cca8..b7ed928 100644
--- a/src/codec/stb_image/impl.c
+++ b/src/codec/stb_image/impl.c
@@ -2,9 +2,9 @@
#include <aki/common.h>
#include "../common.h"
#define STB_IMAGE_IMPLEMENTATION
+#define STB_IMAGE_STATIC
#define STBI_NO_STDIO
#define STBI_NO_FAILURE_STRINGS
-#define STB_IMAGE_STATIC
#define STBI_MALLOC camu_page_alloc
#define STBI_FREE al_free
#define STBI_REALLOC al_realloc