[FFmpeg-cvslog] r14191 - trunk/libavcodec/libdiracenc.c

diego subversion
Sat Jul 12 22:09:50 CEST 2008


Author: diego
Date: Sat Jul 12 22:09:50 2008
New Revision: 14191

Log:
Fix pts handling when encoding with libdirac.
patch by Anuradha Suraparaju, anuradha rd.bbc.co uk


Modified:
   trunk/libavcodec/libdiracenc.c

Modified: trunk/libavcodec/libdiracenc.c
==============================================================================
--- trunk/libavcodec/libdiracenc.c	(original)
+++ trunk/libavcodec/libdiracenc.c	Sat Jul 12 22:09:50 2008
@@ -55,6 +55,12 @@ typedef struct FfmpegDiracEncoderParams
     /** input frame buffer */
     unsigned char *p_in_frame_buf;
 
+    /** buffer to store encoder output before writing it to the frame queue */
+    unsigned char *enc_buf;
+
+    /** size of encoder buffer */
+    int enc_buf_size;
+
     /** queue storing encoded frames */
     FfmpegDiracSchroQueue enc_frame_queue;
 
@@ -236,6 +242,7 @@ static int libdirac_encode_frame(AVCodec
     FfmpegDiracSchroEncodedFrame* p_frame_output = NULL;
     FfmpegDiracSchroEncodedFrame* p_next_output_frame = NULL;
     int go = 1;
+    int last_frame_in_sequence = 0;
 
     if (data == NULL) {
         /* push end of sequence if not already signalled */
@@ -278,18 +285,39 @@ static int libdirac_encode_frame(AVCodec
         case ENC_STATE_AVAIL:
         case ENC_STATE_EOS:
             assert (p_dirac_params->p_encoder->enc_buf.size > 0);
-            /* create output frame */
-            p_frame_output = av_mallocz(sizeof(FfmpegDiracSchroEncodedFrame));
-            /* set output data */
-            p_frame_output->p_encbuf =
-                         av_malloc(p_dirac_params->p_encoder->enc_buf.size);
 
-            memcpy(p_frame_output->p_encbuf,
+            /* All non-frame data is prepended to actual frame data to
+             * be able to set the pts correctly. So we don't write data
+             * to the frame output queue until we actually have a frame
+             */
+
+            p_dirac_params->enc_buf = av_realloc (
+                                      p_dirac_params->enc_buf,
+                                      p_dirac_params->enc_buf_size +
+                                      p_dirac_params->p_encoder->enc_buf.size
+                                      );
+            memcpy(p_dirac_params->enc_buf + p_dirac_params->enc_buf_size,
                    p_dirac_params->p_encoder->enc_buf.buffer,
                    p_dirac_params->p_encoder->enc_buf.size);
 
-            p_frame_output->size = p_dirac_params->p_encoder->enc_buf.size;
+            p_dirac_params->enc_buf_size +=
+                                     p_dirac_params->p_encoder->enc_buf.size;
+
+            if (state == ENC_STATE_EOS) {
+                p_dirac_params->eos_pulled = 1;
+                go = 0;
+            }
+
+            /* If non-frame data, don't output it until it we get an
+             * encoded frame back from the encoder. */
+            if (p_dirac_params->p_encoder->enc_pparams.pnum == -1)
+                break;
 
+            /* create output frame */
+            p_frame_output = av_mallocz(sizeof(FfmpegDiracSchroEncodedFrame));
+            /* set output data */
+            p_frame_output->size     = p_dirac_params->enc_buf_size;
+            p_frame_output->p_encbuf = p_dirac_params->enc_buf;
             p_frame_output->frame_num =
                             p_dirac_params->p_encoder->enc_pparams.pnum;
 
@@ -300,10 +328,8 @@ static int libdirac_encode_frame(AVCodec
             ff_dirac_schro_queue_push_back (&p_dirac_params->enc_frame_queue,
                                             p_frame_output);
 
-            if (state == ENC_STATE_EOS) {
-                p_dirac_params->eos_pulled = 1;
-                go = 0;
-            }
+            p_dirac_params->enc_buf_size = 0;
+            p_dirac_params->enc_buf      = NULL;
             break;
 
         case ENC_STATE_BUFFER:
@@ -322,6 +348,11 @@ static int libdirac_encode_frame(AVCodec
     }
 
     /* copy 'next' frame in queue */
+
+    if (p_dirac_params->enc_frame_queue.size == 1 &&
+        p_dirac_params->eos_pulled)
+        last_frame_in_sequence = 1;
+
     p_next_output_frame =
           ff_dirac_schro_queue_pop(&p_dirac_params->enc_frame_queue);
 
@@ -336,6 +367,17 @@ static int libdirac_encode_frame(AVCodec
     avccontext->coded_frame->pts = p_next_output_frame->frame_num;
     enc_size = p_next_output_frame->size;
 
+    /* Append the end of sequence information to the last frame in the
+     * sequence. */
+    if (last_frame_in_sequence && p_dirac_params->enc_buf_size > 0)
+    {
+        memcpy (frame + enc_size, p_dirac_params->enc_buf,
+                p_dirac_params->enc_buf_size);
+        enc_size += p_dirac_params->enc_buf_size;
+        av_freep (&p_dirac_params->enc_buf);
+        p_dirac_params->enc_buf_size = 0;
+    }
+
     /* free frame */
     DiracFreeFrame(p_next_output_frame);
 
@@ -353,6 +395,10 @@ static int libdirac_encode_close(AVCodec
     ff_dirac_schro_queue_free(&p_dirac_params->enc_frame_queue,
                               DiracFreeFrame);
 
+    /* free the encoder buffer */
+    if (p_dirac_params->enc_buf_size)
+        av_freep(&p_dirac_params->enc_buf);
+
     /* free the input frame buffer */
     av_freep(&p_dirac_params->p_in_frame_buf);
 




More information about the ffmpeg-cvslog mailing list