]> git.sesse.net Git - vlc/blob - modules/packetizer/mpegvideo.c
* mpegvideo: ported to new API (need more clean up).
[vlc] / modules / packetizer / mpegvideo.c
1 /*****************************************************************************
2  * mpegvideo.c
3  *****************************************************************************
4  * Copyright (C) 2001, 2002 VideoLAN
5  * $Id: mpegvideo.c,v 1.22 2003/11/22 16:53:02 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *          Eric Petit <titer@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Problem with this implementation:
27  *
28  * Although we should time-stamp each picture with a PTS, this isn't possible
29  * with the current implementation.
30  * The problem comes from the fact that for non-low-delay streams we can't
31  * calculate the PTS of pictures used as backward reference. Even the temporal
32  * reference number doesn't help here because all the pictures don't
33  * necessarily have the same duration (eg. 3:2 pulldown).
34  *
35  * However this doesn't really matter as far as the MPEG muxers are concerned
36  * because they allow having empty PTS fields. --gibalou
37  *****************************************************************************/
38
39 /*****************************************************************************
40  * Preamble
41  *****************************************************************************/
42 #include <stdlib.h>                                      /* malloc(), free() */
43
44 #include <vlc/vlc.h>
45 #include <vlc/decoder.h>
46 #include <vlc/input.h>
47
48 /*****************************************************************************
49  * Module descriptor
50  *****************************************************************************/
51 static int  Open ( vlc_object_t * );
52 static void Close( vlc_object_t * );
53
54 vlc_module_begin();
55     set_description( _("MPEG-I/II video packetizer") );
56     set_capability( "packetizer", 50 );
57     set_callbacks( Open, Close );
58 vlc_module_end();
59
60
61 /*****************************************************************************
62  * Local prototypes
63  *****************************************************************************/
64 static block_t *Packetize( decoder_t *, block_t ** );
65
66 static int mpgv_FindStartCode( uint8_t **pp_start, uint8_t *p_end );
67
68 struct decoder_sys_t
69 {
70     /* sequence header and extention */
71     block_t *p_seq;
72     block_t *p_ext;
73
74     /* current frame being building */
75     block_t    *p_frame;
76     vlc_bool_t b_frame_slice;
77     vlc_bool_t b_frame_corrupted;
78     vlc_bool_t b_gop;
79
80     /* pts of current picture */
81     mtime_t i_pts;
82     mtime_t i_dts;
83
84     /* gathering buffer */
85     int         i_buffer;
86     int         i_buffer_size;
87     uint8_t     *p_buffer;
88     uint8_t     *p_start, *p_old;
89
90     /* */
91     int         i_frame_rate;
92     int         i_frame_rate_base;
93     vlc_bool_t  b_seq_progressive;
94     vlc_bool_t  b_low_delay;
95
96     /* */
97     int i_temporal_ref;
98     int i_picture_type;
99     int i_picture_structure;
100     int i_top_field_first;
101     int i_repeat_first_field;
102     int i_progressive_frame;
103
104     /* */
105     int     i_seq_old;  /* How many picture from last seq */
106
107     /* */
108
109     mtime_t i_interpolated_dts;
110     mtime_t i_old_duration;
111     mtime_t i_last_ref_pts;
112 };
113
114 /*****************************************************************************
115  * Open:
116  *****************************************************************************/
117 static int Open( vlc_object_t *p_this )
118 {
119     decoder_t *p_dec = (decoder_t*)p_this;
120     decoder_sys_t *p_sys;
121
122     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '1' ) &&
123         p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '2' ) &&
124         p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', 'v' ) )
125     {
126         return VLC_EGENERIC;
127     }
128
129     es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC( 'm', 'p', 'g', 'v' ) );
130     p_dec->pf_packetize = Packetize;
131
132     p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
133
134     p_sys->p_seq = NULL;
135     p_sys->p_ext = NULL;
136     p_sys->p_frame = NULL;
137     p_sys->b_frame_slice = VLC_FALSE;
138     p_sys->b_frame_corrupted = VLC_FALSE;
139     p_sys->b_gop = VLC_FALSE;
140
141     p_sys->i_buffer = 0;
142     p_sys->i_buffer_size = 10000;
143     p_sys->p_buffer = malloc( p_sys->i_buffer_size );
144     p_sys->p_start = p_sys->p_buffer;
145     p_sys->p_old = NULL;
146
147     p_sys->i_dts = 0;
148     p_sys->i_pts = 0;
149
150     p_sys->i_frame_rate = 1;
151     p_sys->i_frame_rate_base = 1;
152     p_sys->b_seq_progressive = VLC_TRUE;
153     p_sys->b_low_delay = VLC_TRUE;
154     p_sys->i_seq_old = 0;
155
156     p_sys->i_temporal_ref = 0;
157     p_sys->i_picture_type = 0;
158     p_sys->i_picture_structure = 0x03; /* frame */
159     p_sys->i_top_field_first = 0;
160     p_sys->i_repeat_first_field = 0;
161     p_sys->i_progressive_frame = 0;
162
163     p_sys->i_interpolated_dts = 0;
164     p_sys->i_old_duration = 0;
165     p_sys->i_last_ref_pts = 0;
166
167     return VLC_SUCCESS;
168 }
169
170 /*****************************************************************************
171  * Close:
172  *****************************************************************************/
173 static void Close( vlc_object_t *p_this )
174 {
175     decoder_t     *p_dec = (decoder_t*)p_this;
176     decoder_sys_t *p_sys = p_dec->p_sys;
177
178     if( p_sys->p_seq )
179     {
180         block_Release( p_sys->p_seq );
181     }
182     if( p_sys->p_ext )
183     {
184         block_Release( p_sys->p_ext );
185     }
186     if( p_sys->p_frame )
187     {
188         block_Release( p_sys->p_frame );
189     }
190     free( p_sys->p_buffer );
191     free( p_sys );
192 }
193
194 /*****************************************************************************
195  * Packetize:
196  *****************************************************************************/
197 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
198 {
199     decoder_sys_t *p_sys = p_dec->p_sys;
200     block_t       *p_chain_out = NULL;
201     block_t       *p_block;
202
203     if( pp_block == NULL || *pp_block == NULL )
204     {
205         return NULL;
206     }
207     p_block = *pp_block;
208     *pp_block = NULL;
209
210     if( p_block->b_discontinuity )
211     {
212         p_sys->b_frame_corrupted = VLC_TRUE;
213     }
214
215     /* Append data */
216     if( p_sys->i_buffer + p_block->i_buffer > p_sys->i_buffer_size )
217     {
218         uint8_t *p_buffer = p_sys->p_buffer;
219
220         p_sys->i_buffer_size += p_block->i_buffer + 1024;
221         p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
222
223         if( p_sys->p_start )
224         {
225             p_sys->p_start = p_sys->p_start - p_buffer + p_sys->p_buffer;
226         }
227         if( p_sys->p_old )
228         {
229             p_sys->p_old = p_sys->p_old - p_buffer + p_sys->p_buffer;
230         }
231
232     }
233     memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer,
234             p_block->i_buffer );
235     p_sys->i_buffer += p_block->i_buffer;
236
237
238     if( p_sys->i_buffer > 10*1000000 )
239     {
240         msg_Err( p_dec, "mmh reseting context" );
241         p_sys->i_buffer = 0;
242     }
243
244     /* Split data in block */
245     for( ;; )
246     {
247         if( mpgv_FindStartCode( &p_sys->p_start, &p_sys->p_buffer[p_sys->i_buffer] ) )
248         {
249             block_Release( p_block );
250
251             if( p_sys->p_seq == NULL )
252             {
253                 block_ChainRelease( p_chain_out );
254                 return NULL;
255             }
256             return p_chain_out;
257         }
258
259         if( p_sys->p_old )
260         {
261             /* Extract the data */
262             int i_frag = p_sys->p_start - p_sys->p_old;
263             block_t *p_frag = block_New( p_dec, i_frag );
264
265             memcpy( p_frag->p_buffer, p_sys->p_old, i_frag );
266             if( i_frag < p_sys->i_buffer )
267             {
268                 memmove( p_sys->p_buffer, &p_sys->p_buffer[i_frag],
269                          p_sys->i_buffer - i_frag );
270             }
271             p_sys->i_buffer -= i_frag;
272             p_sys->p_start -= i_frag;
273             p_sys->p_old   -= i_frag;
274
275             if( p_sys->b_frame_slice && ( p_frag->p_buffer[3] == 0x00 || p_frag->p_buffer[3] > 0xaf ) )
276             {
277                 /* We have a complete picture output it */
278                 if( p_sys->p_seq == NULL )
279                 {
280                     msg_Dbg( p_dec, "waiting sequence start" );
281                     block_ChainRelease( p_sys->p_frame );
282                 }
283                 else if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 && p_sys->i_interpolated_dts <= 0 )
284                 {
285                     msg_Dbg( p_dec, "need a starting pts/dts" );
286                     block_ChainRelease( p_sys->p_frame );
287                 }
288                 else if( p_sys->b_frame_corrupted )
289                 {
290                     msg_Warn( p_dec, "trashing a corrupted picture" );
291                     block_ChainRelease( p_sys->p_frame );
292                     p_sys->b_frame_corrupted = VLC_FALSE;
293                 }
294                 else
295                 {
296                     block_t *p_pic = block_ChainGather( p_sys->p_frame );
297                     mtime_t i_duration = (mtime_t)( 1000000 * p_sys->i_frame_rate_base / p_sys->i_frame_rate);
298
299                     if( !p_sys->b_seq_progressive && p_sys->i_picture_structure != 0x03 )
300                     {
301                         i_duration /= 2;
302                     }
303
304                     if( p_sys->b_seq_progressive )
305                     {
306                         if( p_sys->i_top_field_first == 0 && p_sys->i_repeat_first_field == 1 )
307                         {
308                             i_duration *= 2;
309                         }
310                         else if( p_sys->i_top_field_first == 1 && p_sys->i_repeat_first_field == 1 )
311                         {
312                             i_duration *= 3;
313                         }
314                     }
315                     else
316                     {
317                         if( p_sys->i_picture_structure == 0x03 )
318                         {
319                             if( p_sys->i_progressive_frame && p_sys->i_repeat_first_field )
320                             {
321                                 i_duration += i_duration / 2;
322                             }
323                         }
324                     }
325
326                     if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
327                     {
328                         /* Trivial case (DTS == PTS) */
329                         /* Correct interpolated dts when we receive a new pts/dts */
330                         if( p_sys->i_pts > 0 ) p_sys->i_interpolated_dts = p_sys->i_pts;
331                         if( p_sys->i_dts > 0 ) p_sys->i_interpolated_dts = p_sys->i_dts;
332                     }
333                     else
334                     {
335                         /* Correct interpolated dts when we receive a new pts/dts */
336                         if( p_sys->i_last_ref_pts > 0 )
337                             p_sys->i_interpolated_dts = p_sys->i_last_ref_pts;
338                         if( p_sys->i_dts > 0 ) p_sys->i_interpolated_dts = p_sys->i_dts;
339
340                         p_sys->i_last_ref_pts = p_sys->i_pts;
341                     }
342
343                     p_pic->i_dts    = p_sys->i_interpolated_dts;
344                     /* Set PTS only if I frame or come from stream */
345                     if( p_sys->i_pts > 0 )
346                     {
347                         p_pic->i_pts    = p_sys->i_pts;
348                     }
349                     else if( p_sys->i_picture_type == 0x03 )
350                     {
351                         p_pic->i_pts = p_pic->i_dts;
352                     }
353                     else
354                     {
355                         p_pic->i_pts = -1;
356                     }
357
358                     if( p_sys->b_low_delay || p_sys->i_picture_type == 0x03 )
359                     {
360                         /* Trivial case (DTS == PTS) */
361                         p_sys->i_interpolated_dts += i_duration;
362                     }
363                     else
364                     {
365                         p_sys->i_interpolated_dts += p_sys->i_old_duration;
366                         p_sys->i_old_duration = i_duration;
367                     }
368
369                     p_pic->i_length = p_sys->i_interpolated_dts - p_pic->i_dts;
370
371                     //msg_Dbg( p_dec, "pic: type=%d dts=%lld pts-dts=%lld", p_sys->i_picture_type, p_pic->i_dts, p_pic->i_pts - p_pic->i_dts);
372
373                     block_ChainAppend( &p_chain_out, p_pic );
374
375                 }
376
377                 /* reset context */
378                 p_sys->p_frame = NULL;
379                 p_sys->b_frame_slice = VLC_FALSE;
380                 p_sys->b_gop = VLC_FALSE;
381                 p_sys->i_pts = 0;
382                 p_sys->i_dts = 0;
383             }
384
385             if( p_frag->p_buffer[3] == 0xb8 )
386             {
387                 if( p_sys->p_seq &&
388                     p_sys->i_seq_old > p_sys->i_frame_rate/p_sys->i_frame_rate_base )
389                 {
390                     /* Usefull for mpeg1: repeat sequence header every second */
391                     block_ChainAppend( &p_sys->p_frame,
392                                        block_Duplicate( p_sys->p_seq ) );
393                     if( p_sys->p_ext )
394                     {
395                         block_ChainAppend( &p_sys->p_frame,
396                                            block_Duplicate( p_sys->p_ext ) );
397                     }
398
399                     p_sys->i_seq_old = 0;
400                 }
401                 p_sys->b_gop = VLC_TRUE;
402             }
403             else if( p_frag->p_buffer[3] == 0xb3 )
404             {
405                 static const int code_to_frame_rate[16][2] =
406                 {
407                     { 1, 1 },   /* invalid */
408                     { 24000, 1001 }, { 24, 1 }, { 25, 1 },       { 30000, 1001 },
409                     { 30, 1 },       { 50, 1 }, { 60000, 1001 }, { 60, 1 },
410                     { 1, 1 },        { 1, 1 },  { 1, 1 },        { 1, 1 },  /* invalid */
411                     { 1, 1 },        { 1, 1 },  { 1, 1 }                    /* invalid */
412                 };
413
414                 /* sequence header */
415                 if( p_sys->p_seq )
416                 {
417                     block_Release( p_sys->p_seq );
418                 }
419                 if( p_sys->p_ext )
420                 {
421                     block_Release( p_sys->p_ext );
422                     p_sys->p_ext = NULL;
423                 }
424                 p_sys->p_seq = block_Duplicate( p_frag );
425                 p_sys->i_seq_old = 0;
426
427                 p_dec->fmt_out.video.i_width = ( p_frag->p_buffer[4] << 4)|(p_frag->p_buffer[5] >> 4 );
428                 p_dec->fmt_out.video.i_height= ( (p_frag->p_buffer[5]&0x0f) << 8 )|p_frag->p_buffer[6];
429
430                 p_sys->i_frame_rate = code_to_frame_rate[p_frag->p_buffer[7]&0x0f][0];
431                 p_sys->i_frame_rate_base = code_to_frame_rate[p_frag->p_buffer[7]&0x0f][1];
432
433
434                 p_sys->b_seq_progressive = VLC_TRUE;
435                 p_sys->b_low_delay = VLC_TRUE;
436
437                 msg_Dbg( p_dec, "Size %dx%d fps=%.3f",
438                          p_dec->fmt_out.video.i_width,
439                          p_dec->fmt_out.video.i_height,
440                          (float)p_sys->i_frame_rate / (float)p_sys->i_frame_rate_base );
441             }
442             else if( p_frag->p_buffer[3] == 0xb5 )
443             {
444                 int i_type = p_frag->p_buffer[4] >> 4;
445                 /* extention start code */
446                 if( i_type == 0x01 )
447                 {
448                     /* sequence extention */
449                     if( p_sys->p_ext)
450                     {
451                         block_Release( p_sys->p_ext );
452                     }
453                     p_sys->p_ext = block_Duplicate( p_frag );
454
455                     if( p_frag->i_buffer >= 10 )
456                     {
457                         p_sys->b_seq_progressive = p_frag->p_buffer[5]&0x08 ? VLC_TRUE : VLC_FALSE;
458                         p_sys->b_low_delay = p_frag->p_buffer[9]&0x80 ? VLC_TRUE : VLC_FALSE;
459                     }
460                 }
461                 else if( i_type == 0x08 )
462                 {
463                     /* picture extention */
464                     p_sys->i_picture_structure = p_frag->p_buffer[6]&0x03;
465                     p_sys->i_top_field_first   = p_frag->p_buffer[7] >> 7;
466                     p_sys->i_repeat_first_field= (p_frag->p_buffer[7]>>1)&0x01;
467                     p_sys->i_progressive_frame = p_frag->p_buffer[8] >> 7;
468                 }
469             }
470             else if( p_frag->p_buffer[3] == 0x00 )
471             {
472                 /* picture */
473                 p_sys->i_seq_old++;
474
475                 if( p_frag->i_buffer >= 6 )
476                 {
477                     p_sys->i_temporal_ref = ( p_frag->p_buffer[4] << 2 )|(p_frag->p_buffer[5] >> 6);
478                     p_sys->i_picture_type = ( p_frag->p_buffer[5] >> 3 )&0x03;
479                 }
480                 if( !p_sys->b_frame_slice )
481                 {
482                     p_sys->i_dts = p_block->i_dts; p_block->i_dts = 0;
483                     p_sys->i_pts = p_block->i_pts; p_block->i_pts = 0;
484                 }
485             }
486             else if( p_frag->p_buffer[3] >= 0x01 && p_frag->p_buffer[3] <= 0xaf )
487             {
488                 /* Slice */
489                 p_sys->b_frame_slice = VLC_TRUE;
490             }
491
492             /* Append the block */
493             block_ChainAppend( &p_sys->p_frame, p_frag );
494         }
495         p_sys->p_old = p_sys->p_start;
496         p_sys->p_start += 4;
497     }
498 }
499
500 static int mpgv_FindStartCode( uint8_t **pp_start, uint8_t *p_end )
501 {
502     uint8_t *p = *pp_start;
503
504     for( p = *pp_start; p < p_end - 4; p++ )
505     {
506         if( p[0] == 0 && p[1] == 0 && p[2] == 1 )
507         {
508             *pp_start = p;
509             return VLC_SUCCESS;
510         }
511     }
512
513     *pp_start = p;
514     return VLC_EGENERIC;
515 }
516
517