9 #include "vd_internal.h"
11 //#undef MPEG12_POSTPROC
13 static vd_info_t info
=
15 "MPEG 1/2 Video decoder libmpeg2-v0.4.0b",
17 "A'rpi & Fabian Franz",
22 LIBVD_EXTERN(libmpeg2
)
24 //#include "libvo/video_out.h" // FIXME!!!
26 #include "libmpeg2/mpeg2.h"
27 #include "libmpeg2/attributes.h"
28 #include "libmpeg2/mpeg2_internal.h"
30 #include "../cpudetect.h"
32 // to set/get/query special features/parameters
33 static int control(sh_video_t
*sh
,int cmd
,void* arg
,...){
34 mpeg2dec_t
* mpeg2dec
= sh
->context
;
35 const mpeg2_info_t
* info
= mpeg2_info (mpeg2dec
);
38 case VDCTRL_QUERY_FORMAT
:
39 if (info
->sequence
->width
>> 1 == info
->sequence
->chroma_width
&&
40 info
->sequence
->height
>> 1 == info
->sequence
->chroma_height
&&
41 (*((int*)arg
)) == IMGFMT_YV12
)
43 if (info
->sequence
->width
>> 1 == info
->sequence
->chroma_width
&&
44 info
->sequence
->height
== info
->sequence
->chroma_height
&&
45 (*((int*)arg
)) == IMGFMT_422P
)
50 return CONTROL_UNKNOWN
;
54 static int init(sh_video_t
*sh
){
55 mpeg2dec_t
* mpeg2dec
;
56 // const mpeg2_info_t * info;
61 accel
|= MPEG2_ACCEL_X86_MMX
;
63 accel
|= MPEG2_ACCEL_X86_MMXEXT
;
65 accel
|= MPEG2_ACCEL_X86_3DNOW
;
66 if(gCpuCaps
.hasAltiVec
)
67 accel
|= MPEG2_ACCEL_PPC_ALTIVEC
;
69 accel
|= MPEG2_ACCEL_SPARC_VIS
;
73 mpeg2dec
= mpeg2_init ();
75 if(!mpeg2dec
) return 0;
77 mpeg2_custom_fbuf(mpeg2dec
,1); // enable DR1
81 mpeg2dec
->pending_buffer
= 0;
82 mpeg2dec
->pending_length
= 0;
88 static void uninit(sh_video_t
*sh
){
89 mpeg2dec_t
* mpeg2dec
= sh
->context
;
90 if (mpeg2dec
->pending_buffer
) free(mpeg2dec
->pending_buffer
);
91 mpeg2dec
->decoder
.convert
=NULL
;
92 mpeg2dec
->decoder
.convert_id
=NULL
;
93 mpeg2_close (mpeg2dec
);
96 static void draw_slice (void * _sh
, uint8_t * const * src
, unsigned int y
){
97 sh_video_t
* sh
= (sh_video_t
*) _sh
;
98 mpeg2dec_t
* mpeg2dec
= sh
->context
;
99 const mpeg2_info_t
* info
= mpeg2_info (mpeg2dec
);
102 // printf("draw_slice() y=%d \n",y);
104 stride
[0]=mpeg2dec
->decoder
.stride
;
105 stride
[1]=stride
[2]=mpeg2dec
->decoder
.uv_stride
;
107 mpcodecs_draw_slice(sh
, (uint8_t **)src
,
108 stride
, info
->sequence
->picture_width
,
109 (y
+16<=info
->sequence
->picture_height
) ? 16 :
110 info
->sequence
->picture_height
-y
,
115 static mp_image_t
* decode(sh_video_t
*sh
,void* data
,int len
,int flags
){
116 mpeg2dec_t
* mpeg2dec
= sh
->context
;
117 const mpeg2_info_t
* info
= mpeg2_info (mpeg2dec
);
118 int drop_frame
, framedrop
=flags
&3;
120 // MPlayer registers its own draw_slice callback, prevent libmpeg2 from freeing the context
121 mpeg2dec
->decoder
.convert
=NULL
;
122 mpeg2dec
->decoder
.convert_id
=NULL
;
124 if(len
<=0) return NULL
; // skipped null frame
126 // append extra 'end of frame' code:
127 ((char*)data
+len
)[0]=0;
128 ((char*)data
+len
)[1]=0;
129 ((char*)data
+len
)[2]=1;
130 ((char*)data
+len
)[3]=0xff;
133 if (mpeg2dec
->pending_length
) {
134 mpeg2_buffer (mpeg2dec
, mpeg2dec
->pending_buffer
, mpeg2dec
->pending_buffer
+ mpeg2dec
->pending_length
);
136 mpeg2_buffer (mpeg2dec
, data
, data
+len
);
140 int state
=mpeg2_parse (mpeg2dec
);
141 int type
, use_callback
;
146 if (mpeg2dec
->pending_length
) {
147 // just finished the pending data, continue with processing of the passed buffer
148 mpeg2dec
->pending_length
= 0;
149 mpeg2_buffer (mpeg2dec
, data
, data
+len
);
151 // parsing of the passed buffer finished, return.
156 // video parameters inited/changed, (re)init libvo:
157 if (info
->sequence
->width
>> 1 == info
->sequence
->chroma_width
&&
158 info
->sequence
->height
>> 1 == info
->sequence
->chroma_height
) {
159 if(!mpcodecs_config_vo(sh
,
160 info
->sequence
->picture_width
,
161 info
->sequence
->picture_height
, IMGFMT_YV12
)) return 0;
162 } else if (info
->sequence
->width
>> 1 == info
->sequence
->chroma_width
&&
163 info
->sequence
->height
== info
->sequence
->chroma_height
) {
164 if(!mpcodecs_config_vo(sh
,
165 info
->sequence
->picture_width
,
166 info
->sequence
->picture_height
, IMGFMT_422P
)) return 0;
170 type
=info
->current_picture
->flags
&PIC_MASK_CODING_TYPE
;
172 drop_frame
= framedrop
&& (mpeg2dec
->decoder
.coding_type
== B_TYPE
);
173 drop_frame
|= framedrop
>=2; // hard drop
175 mpeg2_skip(mpeg2dec
, 1);
176 //printf("Dropping Frame ...\n");
179 mpeg2_skip(mpeg2dec
, 0); //mpeg2skip skips frames until set again to 0
181 use_callback
= (!framedrop
&& vd_use_slices
&&
182 (info
->current_picture
->flags
&PIC_FLAG_PROGRESSIVE_FRAME
)) ?
183 MP_IMGFLAG_DRAW_CALLBACK
:0;
185 // get_buffer "callback":
186 mpi_new
=mpcodecs_get_image(sh
,MP_IMGTYPE_IPB
,
187 (type
==PIC_FLAG_CODING_TYPE_B
) ?
188 use_callback
: (MP_IMGFLAG_PRESERVE
|MP_IMGFLAG_READABLE
),
189 info
->sequence
->width
,
190 info
->sequence
->height
);
192 if(!mpi_new
) return 0; // VO ERROR!!!!!!!!
193 mpeg2_set_buf(mpeg2dec
, mpi_new
->planes
, mpi_new
);
194 if (info
->current_picture
->flags
&PIC_FLAG_TOP_FIELD_FIRST
)
195 mpi_new
->fields
|= MP_IMGFIELD_TOP_FIRST
;
196 else mpi_new
->fields
&= ~MP_IMGFIELD_TOP_FIRST
;
197 if (info
->current_picture
->flags
&PIC_FLAG_REPEAT_FIRST_FIELD
)
198 mpi_new
->fields
|= MP_IMGFIELD_REPEAT_FIRST
;
199 else mpi_new
->fields
&= ~MP_IMGFIELD_REPEAT_FIRST
;
200 mpi_new
->fields
|= MP_IMGFIELD_ORDERED
;
202 #ifdef MPEG12_POSTPROC
203 if(!mpi_new
->qscale
){
204 mpi_new
->qstride
=info
->sequence
->width
>>4;
205 mpi_new
->qscale
=malloc(mpi_new
->qstride
*(info
->sequence
->height
>>4));
207 mpeg2dec
->decoder
.quant_store
=mpi_new
->qscale
;
208 mpeg2dec
->decoder
.quant_stride
=mpi_new
->qstride
;
209 mpi_new
->pict_type
=type
; // 1->I, 2->P, 3->B
210 mpi_new
->qscale_type
= 1;
213 if (mpi_new
->flags
&MP_IMGFLAG_DRAW_CALLBACK
214 && !(mpi_new
->flags
&MP_IMGFLAG_DIRECT
)) {
215 // nice, filter/vo likes draw_callback :)
216 mpeg2dec
->decoder
.convert
=draw_slice
;
217 mpeg2dec
->decoder
.convert_id
=sh
;
219 mpeg2dec
->decoder
.convert
=NULL
;
220 mpeg2dec
->decoder
.convert_id
=NULL
;
226 case STATE_INVALID_END
:
228 if(info
->display_fbuf
) {
229 mp_image_t
* mpi
= info
->display_fbuf
->id
;
230 if (mpeg2dec
->pending_length
== 0) {
231 mpeg2dec
->pending_length
= mpeg2dec
->buf_end
- mpeg2dec
->buf_start
;
232 mpeg2dec
->pending_buffer
= realloc(mpeg2dec
->pending_buffer
, mpeg2dec
->pending_length
);
233 memcpy(mpeg2dec
->pending_buffer
, mpeg2dec
->buf_start
, mpeg2dec
->pending_length
);
235 // still some data in the pending buffer, shouldn't happen
236 mpeg2dec
->pending_length
= mpeg2dec
->buf_end
- mpeg2dec
->buf_start
;
237 memmove(mpeg2dec
->pending_buffer
, mpeg2dec
->buf_start
, mpeg2dec
->pending_length
);
238 mpeg2dec
->pending_buffer
= realloc(mpeg2dec
->pending_buffer
, mpeg2dec
->pending_length
+ len
);
239 memcpy(mpeg2dec
->pending_buffer
+mpeg2dec
->pending_length
, data
, len
);
240 mpeg2dec
->pending_length
+= len
;
242 // fprintf(stderr, "pending = %d\n", mpeg2dec->pending_length);