Browse code

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

Originally committed as revision 14191 to svn://svn.ffmpeg.org/ffmpeg/trunk

Anuradha Suraparaju authored on 2008/07/13 05:09:50
Showing 1 changed files
... ...
@@ -55,6 +55,12 @@ typedef struct FfmpegDiracEncoderParams
55 55
     /** input frame buffer */
56 56
     unsigned char *p_in_frame_buf;
57 57
 
58
+    /** buffer to store encoder output before writing it to the frame queue */
59
+    unsigned char *enc_buf;
60
+
61
+    /** size of encoder buffer */
62
+    int enc_buf_size;
63
+
58 64
     /** queue storing encoded frames */
59 65
     FfmpegDiracSchroQueue enc_frame_queue;
60 66
 
... ...
@@ -236,6 +242,7 @@ static int libdirac_encode_frame(AVCodecContext *avccontext,
236 236
     FfmpegDiracSchroEncodedFrame* p_frame_output = NULL;
237 237
     FfmpegDiracSchroEncodedFrame* p_next_output_frame = NULL;
238 238
     int go = 1;
239
+    int last_frame_in_sequence = 0;
239 240
 
240 241
     if (data == NULL) {
241 242
         /* push end of sequence if not already signalled */
... ...
@@ -278,18 +285,39 @@ static int libdirac_encode_frame(AVCodecContext *avccontext,
278 278
         case ENC_STATE_AVAIL:
279 279
         case ENC_STATE_EOS:
280 280
             assert (p_dirac_params->p_encoder->enc_buf.size > 0);
281
-            /* create output frame */
282
-            p_frame_output = av_mallocz(sizeof(FfmpegDiracSchroEncodedFrame));
283
-            /* set output data */
284
-            p_frame_output->p_encbuf =
285
-                         av_malloc(p_dirac_params->p_encoder->enc_buf.size);
286 281
 
287
-            memcpy(p_frame_output->p_encbuf,
282
+            /* All non-frame data is prepended to actual frame data to
283
+             * be able to set the pts correctly. So we don't write data
284
+             * to the frame output queue until we actually have a frame
285
+             */
286
+
287
+            p_dirac_params->enc_buf = av_realloc (
288
+                                      p_dirac_params->enc_buf,
289
+                                      p_dirac_params->enc_buf_size +
290
+                                      p_dirac_params->p_encoder->enc_buf.size
291
+                                      );
292
+            memcpy(p_dirac_params->enc_buf + p_dirac_params->enc_buf_size,
288 293
                    p_dirac_params->p_encoder->enc_buf.buffer,
289 294
                    p_dirac_params->p_encoder->enc_buf.size);
290 295
 
291
-            p_frame_output->size = p_dirac_params->p_encoder->enc_buf.size;
296
+            p_dirac_params->enc_buf_size +=
297
+                                     p_dirac_params->p_encoder->enc_buf.size;
298
+
299
+            if (state == ENC_STATE_EOS) {
300
+                p_dirac_params->eos_pulled = 1;
301
+                go = 0;
302
+            }
303
+
304
+            /* If non-frame data, don't output it until it we get an
305
+             * encoded frame back from the encoder. */
306
+            if (p_dirac_params->p_encoder->enc_pparams.pnum == -1)
307
+                break;
292 308
 
309
+            /* create output frame */
310
+            p_frame_output = av_mallocz(sizeof(FfmpegDiracSchroEncodedFrame));
311
+            /* set output data */
312
+            p_frame_output->size     = p_dirac_params->enc_buf_size;
313
+            p_frame_output->p_encbuf = p_dirac_params->enc_buf;
293 314
             p_frame_output->frame_num =
294 315
                             p_dirac_params->p_encoder->enc_pparams.pnum;
295 316
 
... ...
@@ -300,10 +328,8 @@ static int libdirac_encode_frame(AVCodecContext *avccontext,
300 300
             ff_dirac_schro_queue_push_back (&p_dirac_params->enc_frame_queue,
301 301
                                             p_frame_output);
302 302
 
303
-            if (state == ENC_STATE_EOS) {
304
-                p_dirac_params->eos_pulled = 1;
305
-                go = 0;
306
-            }
303
+            p_dirac_params->enc_buf_size = 0;
304
+            p_dirac_params->enc_buf      = NULL;
307 305
             break;
308 306
 
309 307
         case ENC_STATE_BUFFER:
... ...
@@ -322,6 +348,11 @@ static int libdirac_encode_frame(AVCodecContext *avccontext,
322 322
     }
323 323
 
324 324
     /* copy 'next' frame in queue */
325
+
326
+    if (p_dirac_params->enc_frame_queue.size == 1 &&
327
+        p_dirac_params->eos_pulled)
328
+        last_frame_in_sequence = 1;
329
+
325 330
     p_next_output_frame =
326 331
           ff_dirac_schro_queue_pop(&p_dirac_params->enc_frame_queue);
327 332
 
... ...
@@ -336,6 +367,17 @@ static int libdirac_encode_frame(AVCodecContext *avccontext,
336 336
     avccontext->coded_frame->pts = p_next_output_frame->frame_num;
337 337
     enc_size = p_next_output_frame->size;
338 338
 
339
+    /* Append the end of sequence information to the last frame in the
340
+     * sequence. */
341
+    if (last_frame_in_sequence && p_dirac_params->enc_buf_size > 0)
342
+    {
343
+        memcpy (frame + enc_size, p_dirac_params->enc_buf,
344
+                p_dirac_params->enc_buf_size);
345
+        enc_size += p_dirac_params->enc_buf_size;
346
+        av_freep (&p_dirac_params->enc_buf);
347
+        p_dirac_params->enc_buf_size = 0;
348
+    }
349
+
339 350
     /* free frame */
340 351
     DiracFreeFrame(p_next_output_frame);
341 352
 
... ...
@@ -353,6 +395,10 @@ static int libdirac_encode_close(AVCodecContext *avccontext)
353 353
     ff_dirac_schro_queue_free(&p_dirac_params->enc_frame_queue,
354 354
                               DiracFreeFrame);
355 355
 
356
+    /* free the encoder buffer */
357
+    if (p_dirac_params->enc_buf_size)
358
+        av_freep(&p_dirac_params->enc_buf);
359
+
356 360
     /* free the input frame buffer */
357 361
     av_freep(&p_dirac_params->p_in_frame_buf);
358 362