[FFmpeg-devel] [PATCH]E-AC-3 over HDMI

Carl Eugen Hoyos cehoyos
Sun Jun 20 21:17:35 CEST 2010


Hi!

I was not successful when I tried to use the parsers for E-AC3 and TrueHD: 
Both produced the frames given as input as output frames.

I was successful in using the frame-rate of an E-AC-3 stream as indication for 
how many frames I have to concatenate into a data-burst, however. This 
approach even somehow resembles something in the specification I originally 
did not understand ("ensure ... six blocks of audio data"). Patch attached.

I tried something similar to concatenate TrueHD frames using the major sync 
header, but that did not produce a working file: It was significantly too 
short with aplay -r 192000 -c 8 when using a .pkt_offset of 61440.

Please comment, Carl Eugen
-------------- next part --------------
Index: libavformat/spdif.c
===================================================================
--- libavformat/spdif.c	(revision 23655)
+++ libavformat/spdif.c	(working copy)
@@ -82,6 +82,11 @@
     /// function, which generates codec dependent header information.
     /// Sets data_type and data_offset
     int (*header_info) (AVFormatContext *s, AVPacket *pkt);
+
+    uint8_t *hd_buf;                ///< allocated buffer to concatenate hd audio frames
+    int hd_buf_size;                ///< size of the hd audio buffer
+    int hd_buf_count;               ///< number of frames in the hd audio buffer
+    int old_pkt_size;               ///< size of all frames in the hd audio buffer
 } IEC958Context;
 
 //TODO move to DSP
@@ -103,6 +108,31 @@
         dst[i + 0] = bswap_16(src[i + 0]);
 }
 
+static int spdif_header_eac3(AVFormatContext *s, AVPacket *pkt)
+{
+    IEC958Context *ctx = s->priv_data;
+    int repeat, bitstream_mode = pkt->data[6] & 0x7;
+    if (s->streams[0]->codec->bit_rate <= 384000)
+        repeat = 1;
+    else if (s->streams[0]->codec->bit_rate <= 768000)
+        repeat = 2;
+    else
+        repeat = 6;
+
+    ctx->hd_buf = av_fast_realloc(ctx->hd_buf, &ctx->hd_buf_size, ctx->old_pkt_size + pkt->size);
+    memcpy(&ctx->hd_buf[ctx->old_pkt_size], pkt->data, pkt->size);
+    if (++ctx->hd_buf_count < repeat){
+        ctx->pkt_offset = 0;
+        ctx->old_pkt_size += pkt->size;
+        return 0;
+    }
+    ctx->hd_buf_count = ctx->old_pkt_size = 0;
+
+    ctx->data_type  = IEC958_EAC3 | (bitstream_mode << 8);
+    ctx->pkt_offset = 24576;
+    return 0;
+}
+
 static int spdif_header_ac3(AVFormatContext *s, AVPacket *pkt)
 {
     IEC958Context *ctx = s->priv_data;
@@ -230,6 +260,9 @@
     case CODEC_ID_AC3:
         ctx->header_info = spdif_header_ac3;
         break;
+    case CODEC_ID_EAC3:
+	ctx->header_info = spdif_header_eac3;
+	break;
     case CODEC_ID_MP1:
     case CODEC_ID_MP2:
     case CODEC_ID_MP3:
@@ -252,20 +285,28 @@
 {
     IEC958Context *ctx = s->priv_data;
     av_freep(&ctx->buffer);
+    av_freep(&ctx->hd_buf);
     return 0;
 }
 
 static int spdif_write_packet(struct AVFormatContext *s, AVPacket *pkt)
 {
     IEC958Context *ctx = s->priv_data;
-    int ret, padding;
+    int ret, padding, frame_size = pkt->size;
+    uint8_t *frame = pkt->data;
 
-    ctx->pkt_size = FFALIGN(pkt->size, 2) << 3;
     ret = ctx->header_info(s, pkt);
     if (ret < 0)
         return -1;
+    if (!ctx->pkt_offset)
+        return 0;
+    if (ctx->hd_buf){
+        frame = ctx->hd_buf;
+        frame_size = ctx->hd_buf_size;
+    }
+    ctx->pkt_size = FFALIGN(frame_size, 2) << 3;
 
-    padding = (ctx->pkt_offset - BURST_HEADER_SIZE - pkt->size) >> 1;
+    padding = (ctx->pkt_offset - BURST_HEADER_SIZE - frame_size) >> 1;
     if (padding < 0) {
         av_log(s, AV_LOG_ERROR, "bitrate is too high\n");
         return -1;
@@ -277,23 +318,23 @@
     put_le16(s->pb, ctx->pkt_size);  //Pd
 
 #if HAVE_BIGENDIAN
-    put_buffer(s->pb, pkt->data, pkt->size & ~1);
+    put_buffer(s->pb, frame, frame_size & ~1);
 #else
-    av_fast_malloc(&ctx->buffer, &ctx->buffer_size, pkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
+    av_fast_malloc(&ctx->buffer, &ctx->buffer_size, frame_size + FF_INPUT_BUFFER_PADDING_SIZE);
     if (!ctx->buffer)
         return AVERROR(ENOMEM);
-    bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)pkt->data, pkt->size >> 1);
-    put_buffer(s->pb, ctx->buffer, pkt->size & ~1);
+    bswap_buf16((uint16_t *)ctx->buffer, (uint16_t *)frame, frame_size >> 1);
+    put_buffer(s->pb, ctx->buffer, frame_size & ~1);
 #endif
 
     if (pkt->size & 1)
-        put_be16(s->pb, pkt->data[pkt->size - 1]);
+        put_be16(s->pb, ctx->hd_buf[frame_size - 1]);
 
     for (; padding > 0; padding--)
         put_be16(s->pb, 0);
 
     av_log(s, AV_LOG_DEBUG, "type=%x len=%i pkt_offset=%i\n",
-           ctx->data_type, pkt->size, ctx->pkt_offset);
+           ctx->data_type, frame_size, ctx->pkt_offset);
 
     put_flush_packet(s->pb);
     return 0;



More information about the ffmpeg-devel mailing list