Carl Eugen Hoyos <[email protected]> added the comment:

Parts of this patch were applied in r18891, another part in r19215 with a
discussion here:
http://thread.gmane.org/gmane.comp.video.ffmpeg.devel/92175/focus=92472

Remaining patch uploaded.

_____________________________________________________
FFmpeg issue tracker <[email protected]>
<https://roundup.ffmpeg.org/roundup/ffmpeg/issue1300>
_____________________________________________________
Index: libavformat/mpegenc.c
===================================================================
--- libavformat/mpegenc.c	(revision 20875)
+++ libavformat/mpegenc.c	(working copy)
@@ -30,6 +30,8 @@
 #undef NDEBUG
 #include <assert.h>
 
+#define AUDIO_FRAME_PTS_TICKS 150
+
 typedef struct PacketDesc {
     int64_t pts;
     int64_t dts;
@@ -48,7 +50,7 @@
     PacketDesc *premux_packet;
     PacketDesc **next_packet;
     int packet_number;
-    uint8_t lpcm_header[3];
+    uint8_t lpcm_header[5];
     int lpcm_align;
     int bytes_to_iframe;
     int align_iframe;
@@ -350,9 +352,11 @@
                     goto fail;
                 if (st->codec->channels > 8)
                     return -1;
-                stream->lpcm_header[0] = 0x0c;
-                stream->lpcm_header[1] = (st->codec->channels - 1) | (j << 4);
-                stream->lpcm_header[2] = 0x80;
+                stream->lpcm_header[0] = 0; // first_access_unit_pointer MSB
+                stream->lpcm_header[1] = 4; // first_access_unit_pointer LSB (skip 3 header bytes)
+                stream->lpcm_header[2] = 0; // audio_frame_number
+                stream->lpcm_header[3] = (st->codec->channels - 1) | (j << 4);
+                stream->lpcm_header[4] = 0x80;
                 stream->lpcm_align = st->codec->channels * 2;
             } else {
                 stream->id = mpa_id++;
@@ -657,6 +661,16 @@
     int pes_flags;
     int general_pack = 0;  /*"general" pack without data specific to one stream?*/
     int nb_frames;
+    AVCodecContext *avctx = ctx->streams[stream_index]->codec;
+    int aligned_stuffing = 0;
+    int sample_size = 0;
+    if(avctx) {
+        sample_size = av_get_bits_per_sample(avctx->codec_id)/8; // (from pcm_encode_frame)
+        /* av_get_bits_per_sample returns 0 for CODEC_ID_PCM_DVD */
+        if (CODEC_ID_PCM_DVD == avctx->codec_id)
+            /* 2 samples are interleaved per block in PCM_DVD */
+            sample_size = avctx->bits_per_coded_sample * 2 / 8;
+    }
 
     id = stream->id;
 
@@ -835,6 +849,17 @@
             stuffing_size = 0;
         }
 
+        if (s->is_mpeg2 && PRIVATE_STREAM_1 == startcode && id >= 0xa0 ) {
+            int n = avctx->channels * sample_size; // get byte size
+
+            // If necessary, pad header with bytes to align payload with multiple
+            // of audio samples (for all channels).
+            if (payload_size % n ) {
+                aligned_stuffing = payload_size % n;
+                header_len += aligned_stuffing;
+                payload_size -= aligned_stuffing;
+            }
+        }
         nb_frames= get_nb_frames(ctx, stream, payload_size - stuffing_size);
 
         put_be32(ctx->pb, startcode);
@@ -899,6 +924,8 @@
                to prevent accidental generation of start codes. */
             put_byte(ctx->pb, 0xff);
 
+            for(i=0;i<aligned_stuffing;i++)
+                put_byte(ctx->pb, 0xff);
             for(i=0;i<stuffing_size;i++)
                 put_byte(ctx->pb, 0xff);
         }
@@ -906,12 +933,38 @@
         if (startcode == PRIVATE_STREAM_1) {
             put_byte(ctx->pb, id);
             if (id >= 0xa0) {
-                /* LPCM (XXX: check nb_frames) */
-                put_byte(ctx->pb, 7);
-                put_be16(ctx->pb, 4); /* skip 3 header bytes */
-                put_byte(ctx->pb, stream->lpcm_header[0]);
-                put_byte(ctx->pb, stream->lpcm_header[1]);
-                put_byte(ctx->pb, stream->lpcm_header[2]);
+                uint16_t frames = 0;
+                uint16_t frame_pointer = (stream->lpcm_header[0] << 8) | (stream->lpcm_header[1]);
+                uint16_t frame_size = 0;
+
+                if(avctx) {
+                    // 320 bytes for 16-bit/48KHz stereo
+                    frame_size = (sample_size * avctx->channels * avctx->sample_rate * AUDIO_FRAME_PTS_TICKS) / 
+                                 (ctx->streams[stream_index]->time_base.den / ctx->streams[stream_index]->time_base.num);
+                }
+
+                if(!frame_size)
+                    frame_size = 1;
+
+                // Get number of audio frames in payload
+                frames = (payload_size - frame_pointer) / frame_size;
+                if ((payload_size - frame_pointer) % frame_size)
+                    frames++;
+
+                // Generate LPCM header
+                put_byte(ctx->pb, frames);
+                put_be16(ctx->pb, frame_pointer );
+                put_byte(ctx->pb, stream->lpcm_header[2]); // audio_frame_number
+                put_byte(ctx->pb, stream->lpcm_header[3]);
+                put_byte(ctx->pb, stream->lpcm_header[4]);
+
+                // Calc pointer to start of frame in next payload
+                frame_pointer = ((frame_pointer + frames * frame_size) % payload_size);
+
+                // Setup data for next payload
+                stream->lpcm_header[0] = (uint8_t)(frame_pointer >> 8); // set MSB
+                stream->lpcm_header[1] = (uint8_t)frame_pointer;        // set LSB
+                stream->lpcm_header[2] = (stream->lpcm_header[2] + frames) % 20; // result must be 0 to 19
             } else if (id >= 0x40) {
                 /* AC-3 */
                 put_byte(ctx->pb, nb_frames);

Reply via email to