summaryrefslogtreecommitdiffstats
path: root/audio/decode/ad_spdif.c
diff options
context:
space:
mode:
Diffstat (limited to 'audio/decode/ad_spdif.c')
-rw-r--r--audio/decode/ad_spdif.c158
1 files changed, 84 insertions, 74 deletions
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index cc800224e9..c97c62ddaa 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -24,11 +24,16 @@
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
-#include "config.h"
-#include "common/msg.h"
+#include "audio/aframe.h"
+#include "audio/format.h"
#include "common/av_common.h"
+#include "common/codecs.h"
+#include "common/msg.h"
+#include "demux/packet.h"
+#include "demux/stheader.h"
+#include "filters/f_decoder_wrapper.h"
+#include "filters/filter_internal.h"
#include "options/options.h"
-#include "ad.h"
#define OUTBUF_SIZE 65536
@@ -43,8 +48,8 @@ struct spdifContext {
struct mp_aframe *fmt;
int sstride;
struct mp_aframe_pool *pool;
- bool got_eof;
- struct demux_packet *queued_packet;
+
+ struct mp_decoder public;
};
static int write_packet(void *p, uint8_t *buf, int buf_size)
@@ -62,7 +67,8 @@ static int write_packet(void *p, uint8_t *buf, int buf_size)
return buf_size;
}
-static void uninit(struct dec_audio *da)
+// (called on both filter destruction _and_ if lavf fails to init)
+static void destroy(struct mp_filter *da)
{
struct spdifContext *spdif_ctx = da->priv;
AVFormatContext *lavf_ctx = spdif_ctx->lavf_ctx;
@@ -74,26 +80,11 @@ static void uninit(struct dec_audio *da)
av_freep(&lavf_ctx->pb->buffer);
av_freep(&lavf_ctx->pb);
avformat_free_context(lavf_ctx);
- talloc_free(spdif_ctx->queued_packet);
spdif_ctx->lavf_ctx = NULL;
}
}
-static int init(struct dec_audio *da, const char *decoder)
-{
- struct spdifContext *spdif_ctx = talloc_zero(NULL, struct spdifContext);
- da->priv = spdif_ctx;
- spdif_ctx->log = da->log;
- spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx);
-
- if (strcmp(decoder, "spdif_dts_hd") == 0)
- spdif_ctx->use_dts_hd = true;
-
- spdif_ctx->codec_id = mp_codec_to_av_codec_id(da->codec->codec);
- return spdif_ctx->codec_id != AV_CODEC_ID_NONE;
-}
-
-static void determine_codec_params(struct dec_audio *da, AVPacket *pkt,
+static void determine_codec_params(struct mp_filter *da, AVPacket *pkt,
int *out_profile, int *out_rate)
{
struct spdifContext *spdif_ctx = da->priv;
@@ -156,7 +147,7 @@ done:
MP_WARN(da, "Failed to parse codec profile.\n");
}
-static int init_filter(struct dec_audio *da, AVPacket *pkt)
+static int init_filter(struct mp_filter *da, AVPacket *pkt)
{
struct spdifContext *spdif_ctx = da->priv;
@@ -270,39 +261,36 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
return 0;
fail:
- uninit(da);
+ destroy(da);
+ mp_filter_internal_mark_failed(da);
return -1;
}
-
-static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt)
+static void process(struct mp_filter *da)
{
struct spdifContext *spdif_ctx = da->priv;
- if (spdif_ctx->queued_packet || spdif_ctx->got_eof)
- return false;
-
- spdif_ctx->queued_packet = mpkt ? demux_copy_packet(mpkt) : NULL;
- spdif_ctx->got_eof = !mpkt;
- return true;
-}
-
-static bool receive_frame(struct dec_audio *da, struct mp_aframe **out)
-{
- struct spdifContext *spdif_ctx = da->priv;
+ if (!mp_pin_can_transfer_data(da->ppins[1], da->ppins[0]))
+ return;
- if (spdif_ctx->got_eof) {
- spdif_ctx->got_eof = false;
- return false;
+ struct mp_frame inframe = mp_pin_out_read(da->ppins[0]);
+ if (inframe.type == MP_FRAME_EOF) {
+ mp_pin_in_write(da->ppins[1], inframe);
+ return;
+ } else if (inframe.type != MP_FRAME_PACKET) {
+ if (inframe.type) {
+ MP_ERR(da, "unknown frame type\n");
+ mp_filter_internal_mark_failed(da);
+ }
+ return;
}
- if (!spdif_ctx->queued_packet)
- return true;
-
- double pts = spdif_ctx->queued_packet->pts;
+ struct demux_packet *mpkt = inframe.data;
+ struct mp_aframe *out = NULL;
+ double pts = mpkt->pts;
AVPacket pkt;
- mp_set_av_packet(&pkt, spdif_ctx->queued_packet, NULL);
+ mp_set_av_packet(&pkt, mpkt, NULL);
pkt.pts = pkt.dts = 0;
if (!spdif_ctx->lavf_ctx) {
if (init_filter(da, &pkt) < 0)
@@ -316,39 +304,29 @@ static bool receive_frame(struct dec_audio *da, struct mp_aframe **out)
goto done;
}
- *out = mp_aframe_new_ref(spdif_ctx->fmt);
+ out = mp_aframe_new_ref(spdif_ctx->fmt);
int samples = spdif_ctx->out_buffer_len / spdif_ctx->sstride;
- if (mp_aframe_pool_allocate(spdif_ctx->pool, *out, samples) < 0) {
- TA_FREEP(out);
+ if (mp_aframe_pool_allocate(spdif_ctx->pool, out, samples) < 0) {
+ TA_FREEP(&out);
goto done;
}
- uint8_t **data = mp_aframe_get_data_rw(*out);
+ uint8_t **data = mp_aframe_get_data_rw(out);
if (!data) {
- TA_FREEP(out);
+ TA_FREEP(&out);
goto done;
}
memcpy(data[0], spdif_ctx->out_buffer, spdif_ctx->out_buffer_len);
- mp_aframe_set_pts(*out, pts);
+ mp_aframe_set_pts(out, pts);
done:
- talloc_free(spdif_ctx->queued_packet);
- spdif_ctx->queued_packet = NULL;
- return true;
-}
-
-static int control(struct dec_audio *da, int cmd, void *arg)
-{
- struct spdifContext *spdif_ctx = da->priv;
- switch (cmd) {
- case ADCTRL_RESET:
- talloc_free(spdif_ctx->queued_packet);
- spdif_ctx->queued_packet = NULL;
- spdif_ctx->got_eof = false;
- return CONTROL_TRUE;
+ talloc_free(mpkt);
+ if (out) {
+ mp_pin_in_write(da->ppins[1], MAKE_FRAME(MP_FRAME_AUDIO, out));
+ } else {
+ mp_filter_internal_mark_failed(da);
}
- return CONTROL_UNKNOWN;
}
static const int codecs[] = {
@@ -405,12 +383,44 @@ struct mp_decoder_list *select_spdif_codec(const char *codec, const char *pref)
return list;
}
-const struct ad_functions ad_spdif = {
- .name = "spdif",
- .add_decoders = NULL,
- .init = init,
- .uninit = uninit,
- .control = control,
- .send_packet = send_packet,
- .receive_frame = receive_frame,
+static const struct mp_filter_info ad_spdif_filter = {
+ .name = "ad_spdif",
+ .priv_size = sizeof(struct spdifContext),
+ .process = process,
+ .destroy = destroy,
+};
+
+static struct mp_decoder *create(struct mp_filter *parent,
+ struct mp_codec_params *codec,
+ const char *decoder)
+{
+ struct mp_filter *da = mp_filter_create(parent, &ad_spdif_filter);
+ if (!da)
+ return NULL;
+
+ mp_filter_add_pin(da, MP_PIN_IN, "in");
+ mp_filter_add_pin(da, MP_PIN_OUT, "out");
+
+ da->log = mp_log_new(da, parent->log, NULL);
+
+ struct spdifContext *spdif_ctx = da->priv;
+ spdif_ctx->log = da->log;
+ spdif_ctx->pool = mp_aframe_pool_create(spdif_ctx);
+ spdif_ctx->public.f = da;
+
+ if (strcmp(decoder, "spdif_dts_hd") == 0)
+ spdif_ctx->use_dts_hd = true;
+
+ spdif_ctx->codec_id = mp_codec_to_av_codec_id(codec->codec);
+
+
+ if (spdif_ctx->codec_id == AV_CODEC_ID_NONE) {
+ talloc_free(da);
+ return NULL;
+ }
+ return &spdif_ctx->public;
+}
+
+const struct mp_decoder_fns ad_spdif = {
+ .create = create,
};