]> git.sesse.net Git - x264/blob - input/thread.c
Enhanced Avisynth input support
[x264] / input / thread.c
1 /*****************************************************************************
2  * thread.c: x264 threaded input module
3  *****************************************************************************
4  * Copyright (C) 2003-2009 x264 project
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *          Loren Merritt <lorenm@u.washington.edu>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include "muxers.h"
25
26 extern cli_input_t input;
27
28 typedef struct
29 {
30     cli_input_t input;
31     hnd_t p_handle;
32     x264_picture_t pic;
33     x264_pthread_t tid;
34     int next_frame;
35     int frame_total;
36     int in_progress;
37     struct thread_input_arg_t *next_args;
38 } thread_hnd_t;
39
40 typedef struct thread_input_arg_t
41 {
42     thread_hnd_t *h;
43     x264_picture_t *pic;
44     int i_frame;
45     int status;
46 } thread_input_arg_t;
47
48 static int open_file( char *psz_filename, hnd_t *p_handle, x264_param_t *p_param )
49 {
50     thread_hnd_t *h = malloc( sizeof(thread_hnd_t) );
51     if( !h || input.picture_alloc( &h->pic, p_param->i_csp, p_param->i_width, p_param->i_height ) )
52     {
53         fprintf( stderr, "x264 [error]: malloc failed\n" );
54         return -1;
55     }
56     h->input = input;
57     h->p_handle = *p_handle;
58     h->in_progress = 0;
59     h->next_frame = -1;
60     h->next_args = malloc( sizeof(thread_input_arg_t) );
61     if( !h->next_args )
62         return -1;
63     h->next_args->h = h;
64     h->next_args->status = 0;
65     h->frame_total = input.get_frame_total( h->p_handle );
66     thread_input.picture_alloc = h->input.picture_alloc;
67     thread_input.picture_clean = h->input.picture_clean;
68
69     *p_handle = h;
70     return 0;
71 }
72
73 static int get_frame_total( hnd_t handle )
74 {
75     thread_hnd_t *h = handle;
76     return h->frame_total;
77 }
78
79 static void read_frame_thread_int( thread_input_arg_t *i )
80 {
81     i->status = i->h->input.read_frame( i->pic, i->h->p_handle, i->i_frame );
82 }
83
84 static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
85 {
86     thread_hnd_t *h = handle;
87     int ret = 0;
88
89     if( h->next_frame >= 0 )
90     {
91         x264_pthread_join( h->tid, NULL );
92         ret |= h->next_args->status;
93         h->in_progress = 0;
94     }
95
96     if( h->next_frame == i_frame )
97         XCHG( x264_picture_t, *p_pic, h->pic );
98     else
99         ret |= h->input.read_frame( p_pic, h->p_handle, i_frame );
100
101     if( !h->frame_total || i_frame+1 < h->frame_total )
102     {
103         h->next_frame =
104         h->next_args->i_frame = i_frame+1;
105         h->next_args->pic = &h->pic;
106         if( x264_pthread_create( &h->tid, NULL, (void*)read_frame_thread_int, h->next_args ) )
107             return -1;
108         h->in_progress = 1;
109     }
110     else
111         h->next_frame = -1;
112
113     return ret;
114 }
115
116 static int release_frame( x264_picture_t *pic, hnd_t handle )
117 {
118     thread_hnd_t *h = handle;
119     if( h->input.release_frame )
120         return h->input.release_frame( pic, h->p_handle );
121     return 0;
122 }
123
124 static int close_file( hnd_t handle )
125 {
126     thread_hnd_t *h = handle;
127     if( h->in_progress )
128         x264_pthread_join( h->tid, NULL );
129     h->input.close_file( h->p_handle );
130     h->input.picture_clean( &h->pic );
131     free( h->next_args );
132     free( h );
133     return 0;
134 }
135
136 cli_input_t thread_input = { open_file, get_frame_total, NULL, read_frame, release_frame, NULL, close_file };