Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52867 views
1
/*****************************************************************************
2
* fix_vfr_pts.c: vfr pts fixing video filter
3
*****************************************************************************
4
* Copyright (C) 2010-2016 x264 project
5
*
6
* Authors: Steven Walters <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
21
*
22
* This program is also available under a commercial proprietary license.
23
* For more information, contact us at [email protected].
24
*****************************************************************************/
25
26
#include "video.h"
27
#include "internal.h"
28
29
/* This filter calculates and store the frame's duration to the frame data
30
* (if it is not already calculated when the frame arrives to this point)
31
* so it can be used by filters that will need to reconstruct pts due to
32
* out-of-order frame requests */
33
34
typedef struct
35
{
36
hnd_t prev_hnd;
37
cli_vid_filter_t prev_filter;
38
39
/* we need 1 buffer picture and 1 place holder */
40
cli_pic_t buffer;
41
cli_pic_t holder;
42
int buffer_allocated;
43
int holder_frame;
44
int holder_ret;
45
int64_t pts;
46
int64_t last_duration;
47
} fix_vfr_pts_hnd_t;
48
49
cli_vid_filter_t fix_vfr_pts_filter;
50
51
static int init( hnd_t *handle, cli_vid_filter_t *filter, video_info_t *info, x264_param_t *param, char *opt_string )
52
{
53
/* if the input is not vfr, we don't do anything */
54
if( !info->vfr )
55
return 0;
56
fix_vfr_pts_hnd_t *h = calloc( 1, sizeof(fix_vfr_pts_hnd_t) );
57
if( !h )
58
return -1;
59
60
h->holder_frame = -1;
61
h->prev_hnd = *handle;
62
h->prev_filter = *filter;
63
*handle = h;
64
*filter = fix_vfr_pts_filter;
65
66
return 0;
67
}
68
69
static int get_frame( hnd_t handle, cli_pic_t *output, int frame )
70
{
71
fix_vfr_pts_hnd_t *h = handle;
72
/* if we want the holder picture and it errored, return the error. */
73
if( frame == h->holder_frame )
74
{
75
if( h->holder_ret )
76
return h->holder_ret;
77
}
78
else
79
{
80
/* if we have a holder frame and we don't want it, release the frame */
81
if( h->holder_frame > 0 && h->holder_frame < frame && h->prev_filter.release_frame( h->prev_hnd, &h->holder, h->holder_frame ) )
82
return -1;
83
h->holder_frame = -1;
84
if( h->prev_filter.get_frame( h->prev_hnd, &h->holder, frame ) )
85
return -1;
86
}
87
88
/* if the frame's duration is not set already, read the next frame to set it. */
89
if( !h->holder.duration )
90
{
91
/* allocate a buffer picture if we didn't already */
92
if( !h->buffer_allocated )
93
{
94
if( x264_cli_pic_alloc( &h->buffer, h->holder.img.csp, h->holder.img.width, h->holder.img.height ) )
95
return -1;
96
h->buffer_allocated = 1;
97
}
98
h->holder_frame = frame+1;
99
/* copy the current frame to the buffer, release it, and then read in the next frame to the placeholder */
100
if( x264_cli_pic_copy( &h->buffer, &h->holder ) || h->prev_filter.release_frame( h->prev_hnd, &h->holder, frame ) )
101
return -1;
102
h->holder_ret = h->prev_filter.get_frame( h->prev_hnd, &h->holder, h->holder_frame );
103
/* suppress non-monotonic pts warnings by setting the duration to be at least 1 */
104
if( !h->holder_ret )
105
h->last_duration = X264_MAX( h->holder.pts - h->buffer.pts, 1 );
106
h->buffer.duration = h->last_duration;
107
*output = h->buffer;
108
}
109
else
110
*output = h->holder;
111
112
output->pts = h->pts;
113
h->pts += output->duration;
114
115
return 0;
116
}
117
118
static int release_frame( hnd_t handle, cli_pic_t *pic, int frame )
119
{
120
fix_vfr_pts_hnd_t *h = handle;
121
/* if the frame is the buffered one, it's already been released */
122
if( frame == (h->holder_frame - 1) )
123
return 0;
124
return h->prev_filter.release_frame( h->prev_hnd, pic, frame );
125
}
126
127
static void free_filter( hnd_t handle )
128
{
129
fix_vfr_pts_hnd_t *h = handle;
130
h->prev_filter.free( h->prev_hnd );
131
if( h->buffer_allocated )
132
x264_cli_pic_clean( &h->buffer );
133
free( h );
134
}
135
136
cli_vid_filter_t fix_vfr_pts_filter = { "fix_vfr_pts", NULL, init, get_frame, release_frame, free_filter, NULL };
137
138