1 /*****************************************************************************
2 * mash.c: Video decoder using openmash codec implementations
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Sigmund Augdal <sigmunau@idi.ntnu.no>
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.
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.
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 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
35 #include <vlc_block.h>
39 /*****************************************************************************
40 * decoder_sys_t : video decoder descriptor
41 *****************************************************************************/
48 IntraP64Decoder
*p_decoder
;
54 /****************************************************************************
56 ****************************************************************************/
57 static int OpenDecoder ( vlc_object_t
* );
58 static void CloseDecoder ( vlc_object_t
* );
60 static void *DecodeBlock ( decoder_t
*, block_t
** );
63 static picture_t
*DecodeFrame( decoder_t
*, block_t
* );
64 static block_t
*SendFrame ( decoder_t
*, block_t
* );
67 /*****************************************************************************
69 *****************************************************************************/
71 set_description( N_("Video decoder using openmash") )
72 set_capability( "decoder", 50 )
73 set_category( CAT_INPUT
)
74 set_subcategory( SUBCAT_INPUT_VCODEC
)
75 set_callbacks( OpenDecoder
, CloseDecoder
)
78 /*****************************************************************************
79 * OpenDecoder: probe the decoder and return score
80 *****************************************************************************/
81 static int OpenDecoder( vlc_object_t
*p_this
)
83 decoder_t
*p_dec
= (decoder_t
*)p_this
;
86 switch( p_dec
->fmt_in
.i_codec
)
89 case VLC_FOURCC('h','2','6','1'):
90 case VLC_FOURCC('H','2','6','1'):
97 /* Allocate the memory needed to store the decoder's structure */
98 if( ( p_dec
->p_sys
= p_sys
=
99 (decoder_sys_t
*)malloc(sizeof(decoder_sys_t
)) ) == NULL
)
103 p_sys
->b_inited
= false;
104 p_sys
->i_counter
= 0;
106 /* Set output properties */
107 p_dec
->fmt_out
.i_cat
= VIDEO_ES
;
108 p_dec
->fmt_out
.i_codec
= VLC_FOURCC('I','4','2','0');
111 p_dec
->pf_decode_video
= (picture_t
*(*)(decoder_t
*, block_t
**))
113 p_sys
->p_decoder
= new IntraP64Decoder();
119 /*****************************************************************************
120 * CloseDecoder: decoder destruction
121 *****************************************************************************/
122 static void CloseDecoder( vlc_object_t
*p_this
)
124 decoder_t
*p_dec
= (decoder_t
*)p_this
;
125 free( p_dec
->p_sys
);
129 /****************************************************************************
130 * DecodeBlock: the whole thing
131 ****************************************************************************
132 * This function must be fed with complete frames.
133 ****************************************************************************/
134 static void *DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
136 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
139 uint32_t i_video_header
;
141 int cc
, sbit
, ebit
, mba
, gob
, quant
, mvdh
, mvdv
;
142 int i_width
, i_height
;
144 if( !pp_block
|| !*pp_block
) return NULL
;
148 if( !p_sys
->i_pts
&& !p_block
->i_pts
&& !p_block
->i_dts
)
150 /* We've just started the stream, wait for the first PTS. */
151 block_Release( p_block
);
156 /* Date management */
157 if( p_block
->i_pts
> 0 || p_block
->i_dts
> 0 )
159 if( p_block
->i_pts
> 0 ) p_sys
->i_pts
= p_block
->i_pts
;
160 else if( p_block
->i_dts
> 0 ) p_sys
->i_pts
= p_block
->i_dts
;
163 i_video_header
= *(uint32_t*)p_block
->p_buffer
; /* yes, it is native endian */
164 sbit
= i_video_header
>> 29; /* start bit position */
165 ebit
= (i_video_header
>> 26) & 7; /* end bit position */
166 msg_Dbg( p_dec
, "sbit, ebit: %d,%d", sbit
, ebit
);
167 gob
= (i_video_header
>> 20) & 0xf; /* GOB number */
170 msg_Warn( p_dec
, "invalid gob, buggy vic streamer?");
172 mba
= (i_video_header
>> 15) & 0x1f; /* Macroblock address predictor */
173 quant
= (i_video_header
>> 10) & 0x1f; /* quantizer */
174 mvdh
= (i_video_header
>> 5) & 0x1f; /* horizontal motion vector data */
175 mvdv
= i_video_header
& 0x1f; /* vertical motion vector data */
176 cc
= p_block
->i_buffer
- 4;
177 msg_Dbg( p_dec
, "packet size %d", cc
);
179 /* Find out p_vdec->i_raw_size */
180 p_sys
->p_decoder
->decode( p_block
->p_buffer
+ 4 /*bp?*/,
189 i_width
= p_sys
->p_decoder
->width();
190 i_height
= p_sys
->p_decoder
->height();
191 if( !p_sys
->b_inited
)
193 msg_Dbg( p_dec
, "video size is perhaps %dx%d", i_width
,
195 vout_InitFormat( &p_dec
->fmt_out
.video
, VLC_FOURCC('I','4','2','0'),
197 VOUT_ASPECT_FACTOR
* i_width
/ i_height
);
198 p_sys
->b_inited
= true;
202 // p_sys->p_decoder->sync();
203 if( p_block
->i_flags
& BLOCK_FLAG_END_OF_FRAME
)
205 p_pic
= decoder_NewPicture( p_dec
);
208 block_Release( p_block
);
211 p_sys
->p_decoder
->sync();
212 p_sys
->i_counter
= 0;
213 p_frame
= p_sys
->p_decoder
->frame();
214 vlc_memcpy( p_dec
, p_pic
->p
[0].p_pixels
, p_frame
, i_width
*i_height
);
215 p_frame
+= i_width
* i_height
;
216 vlc_memcpy( p_dec
, p_pic
->p
[1].p_pixels
, p_frame
, i_width
*i_height
/4 );
217 p_frame
+= i_width
* i_height
/4;
218 vlc_memcpy( p_dec
, p_pic
->p
[2].p_pixels
, p_frame
, i_width
*i_height
/4 );
219 p_pic
->date
= p_sys
->i_pts
;
221 block_Release( p_block
);