@@ -68,6 +68,7 @@ typedef struct IEC61937Context {
int use_preamble; ///< preamble enabled (disabled for exactly pre-padded DTS)
int extra_bswap; ///< extra bswap for payload (for LE DTS => standard BE DTS)
+ int more_bursts_needed; ///< more bursts needed for the same AVPacket
uint8_t *hd_buf[2]; ///< allocated buffers to concatenate hd audio frames
int hd_buf_size; ///< size of the hd audio buffer (eac3, dts4)
@@ -80,6 +81,7 @@ typedef struct IEC61937Context {
uint16_t truehd_prev_time; ///< input_timing from the last frame
int truehd_prev_size; ///< previous frame size in bytes, including any MAT codes
int truehd_samples_per_frame; ///< samples per frame for padding calculation
+ int truehd_padding_remaining; ///< amount of padding still needed before data
/* AVOptions: */
int dtshd_rate;
@@ -450,7 +452,12 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt)
return AVERROR_INVALIDDATA;
input_timing = AV_RB16(pkt->data + 2);
- if (ctx->truehd_prev_size) {
+
+ if (ctx->truehd_padding_remaining) {
+ /* padding was calculated on previous call and some still remains */
+ padding_remaining = ctx->truehd_padding_remaining;
+
+ } else if (ctx->truehd_prev_size) {
uint16_t delta_samples = input_timing - ctx->truehd_prev_time;
/*
* One multiple-of-48kHz frame is 1/1200 sec and the IEC 61937 rate
@@ -470,8 +477,8 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt)
delta_samples, delta_bytes);
/* sanity check */
- if (padding_remaining < 0 || padding_remaining >= MAT_FRAME_SIZE / 2) {
- avpriv_request_sample(s, "Unusual frame timing: %"PRIu16" => %"PRIu16", %d samples/frame",
+ if (padding_remaining < 0 || padding_remaining >= MAT_PKT_OFFSET * 50) {
+ avpriv_request_sample(s, "Unusual frame timing (%"PRIu16" => %"PRIu16", %d samples/frame)",
ctx->truehd_prev_time, input_timing, ctx->truehd_samples_per_frame);
padding_remaining = 0;
}
@@ -520,6 +527,15 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt)
/* count the remainder of the code as part of frame size */
if (code_len_remaining)
total_frame_size += code_len_remaining;
+
+ if (have_pkt && padding_remaining) {
+ /*
+ * We already have a full burst but padding still remains,
+ * write out the current burst and ask us to be called again
+ * via ctx->more_bursts_needed to avoid filling our buffers.
+ */
+ break;
+ }
}
if (padding_remaining) {
@@ -547,9 +563,14 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt)
ctx->truehd_prev_size = total_frame_size;
ctx->truehd_prev_time = input_timing;
+ ctx->truehd_padding_remaining = padding_remaining;
- av_log(s, AV_LOG_TRACE, "TrueHD frame inserted, total size %d, buffer position %d\n",
- total_frame_size, ctx->hd_buf_filled);
+ if (padding_remaining)
+ av_log(s, AV_LOG_TRACE, "TrueHD frame not yet inserted, %d bytes more padding needed\n",
+ padding_remaining);
+ else
+ av_log(s, AV_LOG_TRACE, "TrueHD frame inserted, total size %d, buffer position %d\n",
+ total_frame_size, ctx->hd_buf_filled);
if (!have_pkt) {
ctx->pkt_offset = 0;
@@ -560,6 +581,8 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt)
ctx->pkt_offset = MAT_PKT_OFFSET;
ctx->out_bytes = MAT_FRAME_SIZE;
ctx->length_code = MAT_FRAME_SIZE;
+ if (padding_remaining)
+ ctx->more_bursts_needed = 1;
return 0;
}
@@ -619,7 +642,7 @@ static av_always_inline void spdif_put_16(IEC61937Context *ctx,
avio_wl16(pb, val);
}
-static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
+static int spdif_write_burst(AVFormatContext *s, AVPacket *pkt)
{
IEC61937Context *ctx = s->priv_data;
int ret, padding;
@@ -629,6 +652,7 @@ static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
ctx->length_code = FFALIGN(pkt->size, 2) << 3;
ctx->use_preamble = 1;
ctx->extra_bswap = 0;
+ ctx->more_bursts_needed = 0;
ret = ctx->header_info(s, pkt);
if (ret < 0)
@@ -671,6 +695,18 @@ static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
return 0;
}
+static int spdif_write_packet(AVFormatContext *s, AVPacket *pkt)
+{
+ IEC61937Context *ctx = s->priv_data;
+ int ret = 0;
+
+ ctx->more_bursts_needed = 1;
+ while (ctx->more_bursts_needed && ret == 0)
+ ret = spdif_write_burst(s, pkt);
+
+ return ret;
+}
+
AVOutputFormat ff_spdif_muxer = {
.name = "spdif",
.long_name = NULL_IF_CONFIG_SMALL("IEC 61937 (used on S/PDIF - IEC958)"),