OSDN Git Service

214444a05a57851f3bfabbc255de161cc49ebae4
[handbrake-jp/handbrake-jp-git.git] / libhb / decmpeg2.c
1 /* $Id: decmpeg2.c,v 1.12 2005/03/03 16:30:42 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://handbrake.m0k.org/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "hb.h"
8
9 #include "mpeg2dec/mpeg2.h"
10
11 /**********************************************************************
12  * hb_libmpeg2_t
13  **********************************************************************
14  * A convenient libmpeg wrapper, used both here and in scan.c
15  *********************************************************************/
16 struct hb_libmpeg2_s
17 {
18     mpeg2dec_t         * libmpeg2;
19     const mpeg2_info_t * info;
20     int                  width;
21     int                  height;
22     int                  rate;
23     int                  got_iframe;
24     int64_t              last_pts;
25 };
26
27 /**********************************************************************
28  * hb_libmpeg2_init
29  **********************************************************************
30  * 
31  *********************************************************************/
32 hb_libmpeg2_t * hb_libmpeg2_init()
33 {
34     hb_libmpeg2_t * m = calloc( sizeof( hb_libmpeg2_t ), 1 );
35     
36     m->libmpeg2 = mpeg2_init();
37     m->info     = mpeg2_info( m->libmpeg2 );
38     m->last_pts = -1;
39
40     return m;
41 }
42
43 /**********************************************************************
44  * hb_libmpeg2_decode
45  **********************************************************************
46  * 
47  *********************************************************************/
48 int hb_libmpeg2_decode( hb_libmpeg2_t * m, hb_buffer_t * buf_es,
49                         hb_list_t * list_raw )
50 {
51     mpeg2_state_t   state;
52     hb_buffer_t   * buf;
53     uint8_t       * data;
54
55     /* Feed libmpeg2 */
56     if( buf_es->start > -1 )
57     {
58         mpeg2_tag_picture( m->libmpeg2, buf_es->start >> 32,
59                            buf_es->start & 0xFFFFFFFF );
60     }
61     mpeg2_buffer( m->libmpeg2, buf_es->data,
62                   buf_es->data + buf_es->size );
63
64     for( ;; )
65     {
66         state = mpeg2_parse( m->libmpeg2 );
67         if( state == STATE_BUFFER )
68         {
69             /* Require some more data */
70             break;
71         }
72         else if( state == STATE_SEQUENCE )
73         {
74             if( !( m->width && m->height && m->rate ) )
75             {
76                 m->width  = m->info->sequence->width;
77                 m->height = m->info->sequence->height;
78                 m->rate   = m->info->sequence->frame_period;
79                 
80                 if( m->rate == 900900 )
81                 {
82                     /* 29.97 fps. 3:2 pulldown might, or might not be
83                        used. I can't find a way to know, so we always
84                        output 23.976 */
85                     m->rate = 1126125;
86                 }
87             }
88         }
89         else if( ( state == STATE_SLICE || state == STATE_END ) &&
90                  m->info->display_fbuf )
91         {
92             if( ( m->info->display_picture->flags &
93                   PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I )
94             {
95                 m->got_iframe = 1;
96             }
97
98             if( m->got_iframe )
99             {
100                 buf  = hb_buffer_init( m->width * m->height * 3 / 2 );
101                 data = buf->data;
102
103                 memcpy( data, m->info->display_fbuf->buf[0],
104                         m->width * m->height );
105                 data += m->width * m->height;
106                 memcpy( data, m->info->display_fbuf->buf[1],
107                         m->width * m->height / 4 );
108                 data += m->width * m->height / 4;
109                 memcpy( data, m->info->display_fbuf->buf[2],
110                         m->width * m->height / 4 );
111
112                 if( m->info->display_picture->flags & PIC_FLAG_TAGS )
113                 {
114                     buf->start =
115                         ( (uint64_t) m->info->display_picture->tag << 32 ) |
116                         ( (uint64_t) m->info->display_picture->tag2 );
117                 }
118                 else if( m->last_pts > -1 )
119                 {
120                     /* For some reason nb_fields is sometimes 1 while it
121                        should be 2 */
122                     buf->start = m->last_pts +
123                         MAX( 2, m->info->display_picture->nb_fields ) *
124                         m->info->sequence->frame_period / 600;
125                 }
126                 else
127                 {
128                     buf->start = -1;
129                 }
130                 m->last_pts = buf->start;
131
132                 hb_list_add( list_raw, buf );
133             }
134         }
135         else if( state == STATE_INVALID )
136         {
137             mpeg2_reset( m->libmpeg2, 0 );
138         }
139     }
140     return 1;
141 }
142
143 /**********************************************************************
144  * hb_libmpeg2_info
145  **********************************************************************
146  * 
147  *********************************************************************/
148 void hb_libmpeg2_info( hb_libmpeg2_t * m, int * width, int * height,
149                         int * rate )
150 {
151     *width  = m->width;
152     *height = m->height;
153     *rate   = m->rate;
154 }
155
156 /**********************************************************************
157  * hb_libmpeg2_close
158  **********************************************************************
159  * 
160  *********************************************************************/
161 void hb_libmpeg2_close( hb_libmpeg2_t ** _m )
162 {
163     hb_libmpeg2_t * m = *_m;
164
165     mpeg2_close( m->libmpeg2 );
166
167     free( m );
168     *_m = NULL;
169 }
170
171 /**********************************************************************
172  * The decmpeg2 work object
173  **********************************************************************
174  * 
175  *********************************************************************/
176 struct hb_work_private_s
177 {
178     hb_libmpeg2_t * libmpeg2;
179     hb_list_t     * list;
180 };
181
182 /**********************************************************************
183  * hb_work_decmpeg2_init
184  **********************************************************************
185  * 
186  *********************************************************************/
187 int decmpeg2Init( hb_work_object_t * w, hb_job_t * job )
188 {
189     hb_work_private_t * pv;
190     
191     pv              = calloc( 1, sizeof( hb_work_private_t ) );
192     w->private_data = pv;
193     
194     pv->libmpeg2 = hb_libmpeg2_init();
195     pv->list     = hb_list_init();
196
197     return 0;
198 }
199
200 /**********************************************************************
201  * Work
202  **********************************************************************
203  * 
204  *********************************************************************/
205 int decmpeg2Work( hb_work_object_t * w, hb_buffer_t ** buf_in,
206                    hb_buffer_t ** buf_out )
207 {
208     hb_work_private_t * pv = w->private_data;
209     hb_buffer_t * buf, * last = NULL;
210
211     hb_libmpeg2_decode( pv->libmpeg2, *buf_in, pv->list );
212
213     *buf_out = NULL;
214     while( ( buf = hb_list_item( pv->list, 0 ) ) )
215     {
216         hb_list_rem( pv->list, buf );
217         if( last )
218         {
219             last->next = buf;
220             last       = buf;
221         }
222         else
223         {
224             *buf_out = buf;
225             last     = buf;
226         }
227     }
228
229     return HB_WORK_OK;
230 }
231
232 /**********************************************************************
233  * Close
234  **********************************************************************
235  * 
236  *********************************************************************/
237 void decmpeg2Close( hb_work_object_t * w )
238 {
239     hb_work_private_t * pv = w->private_data;
240     hb_list_close( &pv->list );
241     hb_libmpeg2_close( &pv->libmpeg2 );
242     free( pv );
243 }
244
245 hb_work_object_t hb_decmpeg2 =
246 {
247     WORK_DECMPEG2,
248     "MPEG-2 decoder (libmpeg2)",
249     decmpeg2Init,
250     decmpeg2Work,
251     decmpeg2Close
252 };
253