OSDN Git Service

1ba4945bcf2cca20c0a592e250920780d5bc654c
[handbrake-jp/handbrake-jp-git.git] / core / Mpeg2Decoder.cpp
1 /* $Id: Mpeg2Decoder.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $
2
3    This file is part of the HandBrake source code.
4    Homepage: <http://beos.titer.org/handbrake/>.
5    It may be used under the terms of the GNU General Public License. */
6
7 #include "Mpeg2Decoder.h"
8 #include "Manager.h"
9 #include "Fifo.h"
10
11 extern "C" {
12 #include <mpeg2dec/mpeg2.h>
13 }
14 #include <ffmpeg/avcodec.h>
15
16 HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title )
17     : HBThread( "mpeg2decoder" )
18 {
19     fManager     = manager;
20     fTitle       = title;
21 }
22
23 void HBMpeg2Decoder::DoWork()
24 {
25     if( !( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) )
26     {
27         return;
28     }
29
30     fPass = fMpeg2Buffer->fPass;
31     Init();
32
33     do
34     {
35         while( fSuspend )
36         {
37             Snooze( 10000 );
38         }
39
40         if( fMpeg2Buffer->fPass != fPass )
41         {
42             Close();
43             fPass = fMpeg2Buffer->fPass;
44             Init();
45         }
46
47         DecodeBuffer();
48     }
49     while( ( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) );
50 }
51
52 void HBMpeg2Decoder::Init()
53 {
54     fLateField = false;
55
56     /* Init libmpeg2 */
57     fHandle = mpeg2_init();
58 }
59
60 void HBMpeg2Decoder::Close()
61 {
62     /* Close libmpeg2 */
63     mpeg2_close( fHandle );
64 }
65
66 void HBMpeg2Decoder::DecodeBuffer()
67 {
68     const mpeg2_info_t * info = mpeg2_info( fHandle );
69
70     /* Feed libmpeg2 */
71     mpeg2_buffer( fHandle, fMpeg2Buffer->fData,
72                   fMpeg2Buffer->fData + fMpeg2Buffer->fSize );
73
74     mpeg2_state_t state;
75     for( ;; )
76     {
77         state = mpeg2_parse( fHandle );
78
79         if( state == STATE_BUFFER )
80         {
81             break;
82         }
83         else if( ( state == STATE_SLICE || state == STATE_END ) &&
84                    info->display_fbuf )
85         {
86             HBBuffer * rawBuffer = new HBBuffer( 3 * fTitle->fInWidth *
87                                                  fTitle->fInHeight / 2 );
88
89             /* TODO : make libmpeg2 write directly in our buffer */
90             memcpy( rawBuffer->fData,
91                     info->display_fbuf->buf[0],
92                     fTitle->fInWidth * fTitle->fInHeight );
93             memcpy( rawBuffer->fData + fTitle->fInWidth *
94                         fTitle->fInHeight,
95                     info->display_fbuf->buf[1],
96                     fTitle->fInWidth * fTitle->fInHeight / 4 );
97             memcpy( rawBuffer->fData + fTitle->fInWidth *
98                         fTitle->fInHeight + fTitle->fInWidth *
99                         fTitle->fInHeight / 4,
100                     info->display_fbuf->buf[2],
101                     fTitle->fInWidth * fTitle->fInHeight / 4 );
102
103             rawBuffer->fPosition = fMpeg2Buffer->fPosition;
104             rawBuffer->fPass     = fPass;
105
106             /* NTSC pulldown kludge */
107             if( info->display_picture->nb_fields == 3 )
108             {
109                 if( fLateField )
110                 {
111                     HBBuffer * buffer =
112                         new HBBuffer( rawBuffer->fSize );
113                     buffer->fPosition = rawBuffer->fPosition;
114                     buffer->fPass     = rawBuffer->fPass;
115                     memcpy( buffer->fData, rawBuffer->fData,
116                             buffer->fSize );
117                     Push( fTitle->fRawFifo, buffer );
118                 }
119                 fLateField = !fLateField;
120             }
121
122             /* Send it to the encoder */
123             if( !( Push( fTitle->fRawFifo, rawBuffer ) ) )
124             {
125                 break;
126             }
127         }
128         else if( state == STATE_INVALID )
129         {
130             /* Shouldn't happen on a DVD */
131             Log( "HBMpeg2Decoder : STATE_INVALID" );
132         }
133     }
134
135     delete fMpeg2Buffer;
136 }
137