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;
|