summaryrefslogtreecommitdiff
blob: 6745e800b6f7e35eaa660eab8f2afa6da539eaca (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
--- ext/libav/gstavviddec.c
+++ ext/libav/gstavviddec.c
@@ -523,6 +523,7 @@ open_failed:
 
 typedef struct
 {
+  GstFFMpegVidDec *ffmpegdec;
   GstVideoCodecFrame *frame;
   gboolean mapped;
   GstVideoFrame vframe;
@@ -530,13 +531,17 @@ typedef struct
 } GstFFMpegVidDecVideoFrame;
 
 static GstFFMpegVidDecVideoFrame *
-gst_ffmpegviddec_video_frame_new (GstVideoCodecFrame * frame)
+gst_ffmpegviddec_video_frame_new (GstFFMpegVidDec * ffmpegdec,
+    GstVideoCodecFrame * frame)
 {
   GstFFMpegVidDecVideoFrame *dframe;
 
   dframe = g_slice_new0 (GstFFMpegVidDecVideoFrame);
+  dframe->ffmpegdec = ffmpegdec;
   dframe->frame = frame;
 
+  GST_DEBUG_OBJECT (ffmpegdec, "new video frame %p", dframe);
+
   return dframe;
 }
 
@@ -544,6 +549,8 @@ static void
 gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
     GstFFMpegVidDecVideoFrame * frame)
 {
+  GST_DEBUG_OBJECT (ffmpegdec, "free video frame %p", frame);
+
   if (frame->mapped)
     gst_video_frame_unmap (&frame->vframe);
   gst_video_decoder_release_frame (GST_VIDEO_DECODER (ffmpegdec), frame->frame);
@@ -551,6 +558,14 @@ gst_ffmpegviddec_video_frame_free (GstFFMpegVidDec * ffmpegdec,
   g_slice_free (GstFFMpegVidDecVideoFrame, frame);
 }
 
+static void
+dummy_free_buffer (void *opaque, uint8_t * data)
+{
+  GstFFMpegVidDecVideoFrame *frame = opaque;
+
+  gst_ffmpegviddec_video_frame_free (frame->ffmpegdec, frame);
+}
+
 /* called when ffmpeg wants us to allocate a buffer to write the decoded frame
  * into. We try to give it memory from our pool */
 static int
@@ -589,7 +604,8 @@ gst_ffmpegviddec_get_buffer (AVCodecContext * context, AVFrame * picture)
     goto duplicate_frame;
 
   /* GstFFMpegVidDecVideoFrame receives the frame ref */
-  picture->opaque = dframe = gst_ffmpegviddec_video_frame_new (frame);
+  picture->opaque = dframe =
+      gst_ffmpegviddec_video_frame_new (ffmpegdec, frame);
 
   GST_DEBUG_OBJECT (ffmpegdec, "storing opaque %p", dframe);
 
@@ -695,12 +711,20 @@ invalid_frame:
 fallback:
   {
     int c;
+    gboolean first = TRUE;
     int ret = avcodec_default_get_buffer (context, picture);
 
     GST_LOG_OBJECT (ffmpegdec, "performing fallback alloc");
-    for (c = 0; c < AV_NUM_DATA_POINTERS; c++)
+    for (c = 0; c < AV_NUM_DATA_POINTERS; c++) {
       ffmpegdec->stride[c] = picture->linesize[c];
 
+      if (picture->buf[c] == NULL && first) {
+        picture->buf[c] =
+            av_buffer_create (NULL, 0, dummy_free_buffer, dframe, 0);
+        first = FALSE;
+      }
+    }
+
     return ret;
   }
 duplicate_frame:
@@ -1684,8 +1718,8 @@ gst_ffmpegviddec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query)
     avcodec_align_dimensions2 (ffmpegdec->context, &width, &height,
         linesize_align);
     edge =
-        ffmpegdec->context->
-        flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width ();
+        ffmpegdec->
+        context->flags & CODEC_FLAG_EMU_EDGE ? 0 : avcodec_get_edge_width ();
     /* increase the size for the padding */
     width += edge << 1;
     height += edge << 1;