1 /*****************************************************************************
\r
2 * dmo.c : DirectMedia Object decoder module for vlc
\r
3 *****************************************************************************
\r
4 * Copyright (C) 2002, 2003 VideoLAN
\r
7 * Author: Gildas Bazin <gbazin@videolan.org>
\r
9 * This program is free software; you can redistribute it and/or modify
\r
10 * it under the terms of the GNU General Public License as published by
\r
11 * the Free Software Foundation; either version 2 of the License, or
\r
12 * (at your option) any later version.
\r
14 * This program is distributed in the hope that it will be useful,
\r
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 * GNU General Public License for more details.
\r
19 * You should have received a copy of the GNU General Public License
\r
20 * along with this program; if not, write to the Free Software
\r
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
\r
22 *****************************************************************************/
\r
24 /*****************************************************************************
\r
26 *****************************************************************************/
\r
31 #include <vlc/vlc.h>
\r
32 #include <vlc/decoder.h>
\r
33 #include <vlc/vout.h>
\r
35 #include <objbase.h>
\r
39 static int pi_channels_maps[7] =
\r
43 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
\r
44 AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
\r
45 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
\r
46 | AOUT_CHAN_REARRIGHT,
\r
47 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
\r
48 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
\r
49 AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
\r
50 | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE
\r
53 /*****************************************************************************
\r
55 *****************************************************************************/
\r
56 static int DecoderOpen ( vlc_object_t * );
\r
57 static void DecoderClose ( vlc_object_t * );
\r
58 static void *DecodeBlock ( decoder_t *, block_t ** );
\r
60 static void CopyPicture( decoder_t *, picture_t *, uint8_t * );
\r
63 set_description( _("DirectMedia Object decoder") );
\r
64 add_shortcut( "dmo" );
\r
65 set_capability( "decoder", 1 );
\r
66 set_callbacks( DecoderOpen, DecoderClose );
\r
69 /*****************************************************************************
\r
71 *****************************************************************************/
\r
73 /****************************************************************************
\r
74 * Decoder descriptor declaration
\r
75 ****************************************************************************/
\r
76 struct decoder_sys_t
\r
78 HINSTANCE hmsdmo_dll;
\r
79 IMediaObject *p_dmo;
\r
84 audio_date_t end_date;
\r
87 /*****************************************************************************
\r
88 * DecoderOpen: open dmo codec
\r
89 *****************************************************************************/
\r
90 static int DecoderOpen( vlc_object_t *p_this )
\r
92 decoder_t *p_dec = (decoder_t*)p_this;
\r
93 decoder_sys_t *p_sys = NULL;
\r
95 DMO_PARTIAL_MEDIATYPE dmo_partial_type;
\r
96 DMO_MEDIA_TYPE dmo_input_type, dmo_output_type;
\r
97 IEnumDMO *p_enum_dmo = NULL;
\r
98 IMediaObject *p_dmo = NULL;
\r
99 WCHAR *psz_dmo_name;
\r
102 VIDEOINFOHEADER *p_vih = NULL;
\r
103 WAVEFORMATEX *p_wf = NULL;
\r
105 HRESULT (STDCALL *OurDMOEnum)( const GUID *, uint32_t, uint32_t,
\r
106 const DMO_PARTIAL_MEDIATYPE *,
\r
107 uint32_t, const DMO_PARTIAL_MEDIATYPE *,
\r
110 /* Load msdmo DLL */
\r
111 HINSTANCE hmsdmo_dll = LoadLibrary( "msdmo.dll" );
\r
112 if( hmsdmo_dll == NULL )
\r
114 msg_Dbg( p_dec, "failed loading msdmo.dll" );
\r
115 return VLC_EGENERIC;
\r
117 OurDMOEnum = (void *)GetProcAddress( hmsdmo_dll, "DMOEnum" );
\r
118 if( OurDMOEnum == NULL )
\r
120 msg_Dbg( p_dec, "GetProcAddress failed to find DMOEnum()" );
\r
121 FreeLibrary( hmsdmo_dll );
\r
122 return VLC_EGENERIC;
\r
125 /* Look for a DMO which can handle the requested codec */
\r
126 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
129 dmo_partial_type.type = MEDIATYPE_Audio;
\r
130 dmo_partial_type.subtype = dmo_partial_type.type;
\r
131 dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;
\r
132 fourcc_to_wf_tag( p_dec->fmt_in.i_codec, &i_tag );
\r
133 if( i_tag ) dmo_partial_type.subtype.Data1 = i_tag;
\r
137 dmo_partial_type.type = MEDIATYPE_Video;
\r
138 dmo_partial_type.subtype = dmo_partial_type.type;
\r
139 dmo_partial_type.subtype.Data1 = p_dec->fmt_in.i_codec;
\r
142 /* Initialize OLE/COM */
\r
145 if( OurDMOEnum( &GUID_NULL, 1 /*DMO_ENUMF_INCLUDE_KEYED*/,
\r
146 1, &dmo_partial_type, 0, NULL, &p_enum_dmo ) )
\r
151 /* Pickup the first available codec */
\r
152 if( p_enum_dmo->vt->Next( p_enum_dmo, 1, &clsid_dmo,
\r
153 &psz_dmo_name, NULL ) )
\r
157 p_enum_dmo->vt->Release( (IUnknown *)p_enum_dmo );
\r
161 char psz_temp[MAX_PATH];
\r
162 wcstombs( psz_temp, psz_dmo_name, MAX_PATH );
\r
163 msg_Dbg( p_dec, "found DMO: %s", psz_temp );
\r
167 CoTaskMemFree( psz_dmo_name );
\r
170 if( CoCreateInstance( &clsid_dmo, NULL, CLSCTX_INPROC,
\r
171 &IID_IMediaObject, (void **)&p_dmo ) )
\r
173 msg_Err( p_dec, "can't create DMO" );
\r
177 /* Setup input format */
\r
178 memset( &dmo_input_type, 0, sizeof(dmo_input_type) );
\r
179 dmo_input_type.majortype = dmo_partial_type.type;
\r
180 dmo_input_type.subtype = dmo_partial_type.subtype;
\r
181 dmo_input_type.pUnk = 0;
\r
183 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
185 int i_size = sizeof(WAVEFORMATEX) + p_dec->fmt_in.i_extra;
\r
186 p_wf = malloc( i_size );
\r
188 memset( p_wf, 0, sizeof(WAVEFORMATEX) );
\r
189 if( p_dec->fmt_in.i_extra )
\r
190 memcpy( &p_wf[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
\r
192 p_wf->wFormatTag = dmo_partial_type.subtype.Data1;
\r
193 p_wf->nSamplesPerSec = p_dec->fmt_in.audio.i_rate;
\r
194 p_wf->nChannels = p_dec->fmt_in.audio.i_channels;
\r
195 p_wf->wBitsPerSample = p_dec->fmt_in.audio.i_bitspersample;
\r
196 p_wf->nBlockAlign = p_dec->fmt_in.audio.i_blockalign;
\r
197 p_wf->nAvgBytesPerSec = p_dec->fmt_in.i_bitrate / 8;
\r
198 p_wf->cbSize = i_size;
\r
200 dmo_input_type.formattype = FORMAT_WaveFormatEx;
\r
201 dmo_input_type.cbFormat = i_size;
\r
202 dmo_input_type.pbFormat = (char *)p_wf;
\r
203 dmo_input_type.pUnk = NULL;
\r
204 dmo_input_type.bFixedSizeSamples = 1;
\r
205 dmo_input_type.bTemporalCompression = 0;
\r
206 dmo_input_type.lSampleSize = p_wf->nBlockAlign;
\r
210 BITMAPINFOHEADER *p_bih;
\r
212 int i_size = sizeof(VIDEOINFOHEADER) + p_dec->fmt_in.i_extra;
\r
213 p_vih = malloc( i_size );
\r
215 memset( p_vih, 0, sizeof(VIDEOINFOHEADER) );
\r
216 if( p_dec->fmt_in.i_extra )
\r
217 memcpy( &p_vih[1], p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra );
\r
219 p_bih = &p_vih->bmiHeader;
\r
220 p_bih->biCompression = dmo_partial_type.subtype.Data1;
\r
221 p_bih->biWidth = p_dec->fmt_in.video.i_width;
\r
222 p_bih->biHeight = p_dec->fmt_in.video.i_height;
\r
223 p_bih->biBitCount = p_dec->fmt_in.video.i_bits_per_pixel;
\r
224 p_bih->biPlanes = 1;
\r
225 p_bih->biSize = i_size - sizeof(VIDEOINFOHEADER) +
\r
226 sizeof(BITMAPINFOHEADER);
\r
228 p_vih->rcSource.left = p_vih->rcSource.top = 0;
\r
229 p_vih->rcSource.right = p_dec->fmt_in.video.i_width;
\r
230 p_vih->rcSource.bottom = p_dec->fmt_in.video.i_height;
\r
231 p_vih->rcTarget = p_vih->rcSource;
\r
233 dmo_input_type.formattype = MEDIASUBTYPE_VideoInfo;
\r
234 dmo_input_type.bFixedSizeSamples = 0;
\r
235 dmo_input_type.bTemporalCompression = 1;
\r
236 dmo_input_type.cbFormat = i_size;
\r
237 dmo_input_type.pbFormat = (char *)p_vih;
\r
240 if( p_dmo->vt->SetInputType( p_dmo, 0, &dmo_input_type, 0 ) )
\r
242 msg_Err( p_dec, "can't set DMO input type" );
\r
245 msg_Dbg( p_dec, "DMO input type set" );
\r
247 /* Setup output format */
\r
248 memset( &dmo_output_type, 0, sizeof(dmo_output_type) );
\r
249 dmo_output_type.majortype = dmo_partial_type.type;
\r
250 dmo_output_type.pUnk = 0;
\r
252 if( p_dec->fmt_in.i_cat == AUDIO_ES )
\r
254 /* Setup the format */
\r
255 p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;
\r
256 p_dec->fmt_out.audio.i_rate = p_dec->fmt_in.audio.i_rate;
\r
257 p_dec->fmt_out.audio.i_channels = p_dec->fmt_in.audio.i_channels;
\r
258 p_dec->fmt_out.audio.i_bitspersample =
\r
259 p_dec->fmt_in.audio.i_bitspersample;
\r
260 p_dec->fmt_out.audio.i_physical_channels =
\r
261 p_dec->fmt_out.audio.i_original_channels =
\r
262 pi_channels_maps[p_dec->fmt_out.audio.i_channels];
\r
264 p_wf->wFormatTag = WAVE_FORMAT_PCM;
\r
265 p_wf->nSamplesPerSec = p_dec->fmt_out.audio.i_rate;
\r
266 p_wf->nChannels = p_dec->fmt_out.audio.i_channels;
\r
267 p_wf->wBitsPerSample = p_dec->fmt_out.audio.i_bitspersample;
\r
268 p_wf->nBlockAlign =
\r
269 p_wf->wBitsPerSample / 8 * p_wf->nChannels;
\r
270 p_wf->nAvgBytesPerSec =
\r
271 p_wf->nSamplesPerSec * p_wf->nBlockAlign;
\r
272 p_wf->cbSize = sizeof(WAVEFORMATEX);
\r
274 dmo_output_type.formattype = FORMAT_WaveFormatEx;
\r
275 dmo_output_type.subtype = MEDIASUBTYPE_PCM;
\r
276 dmo_output_type.cbFormat = sizeof(WAVEFORMATEX);
\r
277 dmo_output_type.pbFormat = (char *)p_wf;
\r
278 dmo_output_type.bFixedSizeSamples = 1;
\r
279 dmo_output_type.bTemporalCompression = 0;
\r
280 dmo_output_type.lSampleSize = p_wf->nBlockAlign;
\r
281 dmo_output_type.pUnk = NULL;
\r
285 BITMAPINFOHEADER *p_bih;
\r
287 p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
\r
288 p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width;
\r
289 p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
\r
290 p_dec->fmt_out.video.i_bits_per_pixel = 12;
\r
291 p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR *
\r
292 p_dec->fmt_out.video.i_width / p_dec->fmt_out.video.i_height;
\r
294 dmo_output_type.formattype = MEDIASUBTYPE_VideoInfo;
\r
295 dmo_output_type.subtype = MEDIASUBTYPE_YV12;
\r
297 p_bih = &p_vih->bmiHeader;
\r
298 p_bih->biCompression = dmo_partial_type.subtype.Data1;
\r
299 p_bih->biHeight *= -1;
\r
300 p_bih->biBitCount = p_dec->fmt_out.video.i_bits_per_pixel;
\r
301 p_bih->biSizeImage = p_dec->fmt_in.video.i_width *
\r
302 p_dec->fmt_in.video.i_height *
\r
303 (p_dec->fmt_in.video.i_bits_per_pixel + 7) / 8;
\r
305 //p_bih->biPlanes = 1;
\r
306 p_bih->biSize = sizeof(BITMAPINFOHEADER);
\r
308 dmo_output_type.bFixedSizeSamples = VLC_TRUE;
\r
309 dmo_output_type.bTemporalCompression = 0;
\r
310 dmo_output_type.lSampleSize = p_bih->biSizeImage;
\r
311 dmo_output_type.cbFormat = sizeof(VIDEOINFOHEADER);
\r
312 dmo_output_type.pbFormat = (char *)p_vih;
\r
315 /* Enumerate output types */
\r
316 if( p_dec->fmt_in.i_cat == VIDEO_ES )
\r
321 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
\r
323 msg_Dbg( p_dec, "available output chroma: %4.4s",
\r
324 (char *)&mt.subtype.Data1 );
\r
328 /* Choose an output type.
\r
329 * FIXME, get rid of the dmo_output_type code above. */
\r
330 if( p_dec->fmt_in.i_cat == VIDEO_ES )
\r
335 while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &mt ) )
\r
337 if( dmo_output_type.subtype.Data1 == mt.subtype.Data1 )
\r
339 *p_vih = *(VIDEOINFOHEADER *)mt.pbFormat;
\r
345 if( p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_output_type, 0 ) )
\r
347 msg_Err( p_dec, "can't set DMO output type" );
\r
350 msg_Dbg( p_dec, "DMO output type set" );
\r
352 /* Allocate the memory needed to store the decoder's structure */
\r
353 if( ( p_dec->p_sys = p_sys =
\r
354 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
\r
356 msg_Err( p_dec, "out of memory" );
\r
360 p_sys->hmsdmo_dll = hmsdmo_dll;
\r
361 p_sys->p_dmo = p_dmo;
\r
363 /* Find out some properties of the output */
\r
365 uint32_t i_size, i_align;
\r
367 p_sys->i_min_output = 0;
\r
368 if( p_dmo->vt->GetOutputSizeInfo( p_dmo, 0, &i_size, &i_align ) )
\r
370 msg_Err( p_dec, "GetOutputSizeInfo() failed" );
\r
375 msg_Dbg( p_dec, "GetOutputSizeInfo(): bytes %i, align %i",
\r
377 p_sys->i_min_output = i_size;
\r
378 p_sys->p_buffer = malloc( i_size );
\r
379 if( !p_sys->p_buffer ) goto error;
\r
383 /* Set output properties */
\r
384 p_dec->fmt_out.i_cat = p_dec->fmt_in.i_cat;
\r
385 if( p_dec->fmt_out.i_cat == AUDIO_ES )
\r
386 aout_DateInit( &p_sys->end_date, p_dec->fmt_in.audio.i_rate );
\r
388 aout_DateInit( &p_sys->end_date, 25 /* FIXME */ );
\r
389 aout_DateSet( &p_sys->end_date, 0 );
\r
391 /* Set callbacks */
\r
392 p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **))
\r
394 p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **))
\r
397 if( p_vih ) free( p_vih );
\r
398 if( p_wf ) free( p_wf );
\r
400 return VLC_SUCCESS;
\r
403 /* Uninitialize OLE/COM */
\r
405 FreeLibrary( hmsdmo_dll );
\r
407 if( p_vih ) free( p_vih );
\r
408 if( p_wf ) free( p_wf );
\r
409 if( p_sys ) free( p_sys );
\r
411 return VLC_EGENERIC;
\r
414 /*****************************************************************************
\r
415 * DecoderClose: close codec
\r
416 *****************************************************************************/
\r
417 void DecoderClose( vlc_object_t *p_this )
\r
419 decoder_t *p_dec = (decoder_t*)p_this;
\r
420 decoder_sys_t *p_sys = p_dec->p_sys;
\r
422 /* Uninitialize OLE/COM */
\r
425 FreeLibrary( p_sys->hmsdmo_dll );
\r
427 if( p_sys->p_buffer ) free( p_sys->p_buffer );
\r
431 /****************************************************************************
\r
432 * DecodeBlock: the whole thing
\r
433 ****************************************************************************
\r
434 * This function must be fed with ogg packets.
\r
435 ****************************************************************************/
\r
436 static void *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
\r
438 decoder_sys_t *p_sys = p_dec->p_sys;
\r
442 DMO_OUTPUT_DATA_BUFFER db;
\r
443 CMediaBuffer *p_out;
\r
445 uint32_t i_status, i_buffer_out;
\r
446 uint8_t *p_buffer_out;
\r
448 if( !pp_block ) return NULL;
\r
450 p_block = *pp_block;
\r
452 /* Won't work with streams with B-frames, but do we have any ? */
\r
453 if( p_block && p_block->i_pts <= 0 ) p_block->i_pts = p_block->i_dts;
\r
455 /* Date management */
\r
456 if( p_block && p_block->i_pts > 0 &&
\r
457 p_block->i_pts != aout_DateGet( &p_sys->end_date ) )
\r
459 aout_DateSet( &p_sys->end_date, p_block->i_pts );
\r
462 #if 0 /* Breaks the video decoding */
\r
463 if( !aout_DateGet( &p_sys->end_date ) )
\r
465 /* We've just started the stream, wait for the first PTS. */
\r
466 if( p_block ) block_Release( p_block );
\r
471 /* Feed input to the DMO */
\r
472 if( p_block && p_block->i_buffer )
\r
474 CMediaBuffer *p_in;
\r
476 p_in = CMediaBufferCreate( p_block, p_block->i_buffer, VLC_TRUE );
\r
478 i_result = p_sys->p_dmo->vt->ProcessInput( p_sys->p_dmo, 0,
\r
479 (IMediaBuffer *)p_in, DMO_INPUT_DATA_BUFFER_SYNCPOINT,
\r
482 p_in->vt->Release( (IUnknown *)p_in );
\r
484 if( i_result == S_FALSE )
\r
486 /* No output generated */
\r
488 msg_Dbg( p_dec, "ProcessInput(): no output generated" );
\r
492 else if( i_result == DMO_E_NOTACCEPTING )
\r
494 /* Need to call ProcessOutput */
\r
495 msg_Dbg( p_dec, "ProcessInput(): not accepting" );
\r
497 else if( i_result != S_OK )
\r
499 msg_Dbg( p_dec, "ProcessInput(): failed" );
\r
504 //msg_Dbg( p_dec, "ProcessInput(): successful" );
\r
508 else if( p_block && !p_block->i_buffer )
\r
510 block_Release( p_block );
\r
514 /* Get output from the DMO */
\r
515 block_out.p_buffer = p_sys->p_buffer;;
\r
516 block_out.i_buffer = 0;
\r
518 p_out = CMediaBufferCreate( &block_out, p_sys->i_min_output, VLC_FALSE );
\r
519 db.rtTimestamp = 0;
\r
520 db.rtTimelength = 0;
\r
522 db.pBuffer = (IMediaBuffer *)p_out;
\r
524 i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo,
\r
525 DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER,
\r
526 1, &db, &i_status );
\r
528 if( i_result != S_OK )
\r
530 if( i_result != S_FALSE )
\r
531 msg_Dbg( p_dec, "ProcessOutput(): failed" );
\r
534 msg_Dbg( p_dec, "ProcessOutput(): no output" );
\r
537 p_out->vt->Release( (IUnknown *)p_out );
\r
542 msg_Dbg( p_dec, "ProcessOutput(): success" );
\r
545 i_result = p_out->vt->GetBufferAndLength( (IMediaBuffer *)p_out,
\r
546 &p_buffer_out, &i_buffer_out );
\r
547 if( i_result != S_OK )
\r
549 msg_Dbg( p_dec, "GetBufferAndLength(): failed" );
\r
550 p_out->vt->Release( (IUnknown *)p_out );
\r
554 if( !i_buffer_out )
\r
557 msg_Dbg( p_dec, "ProcessOutput(): no output (i_buffer_out == 0)" );
\r
559 p_out->vt->Release( (IUnknown *)p_out );
\r
563 if( p_dec->fmt_out.i_cat == VIDEO_ES )
\r
565 /* Get a new picture */
\r
566 picture_t *p_pic = p_dec->pf_vout_buffer_new( p_dec );
\r
567 if( !p_pic ) return NULL;
\r
569 CopyPicture( p_dec, p_pic, block_out.p_buffer );
\r
571 /* Date management */
\r
572 p_pic->date = aout_DateGet( &p_sys->end_date );
\r
573 aout_DateIncrement( &p_sys->end_date, 1 );
\r
575 p_out->vt->Release( (IUnknown *)p_out );
\r
581 aout_buffer_t *p_aout_buffer;
\r
582 int i_samples = i_buffer_out /
\r
583 ( p_dec->fmt_in.audio.i_bitspersample *
\r
584 p_dec->fmt_in.audio.i_channels / 8 );
\r
586 p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples );
\r
587 memcpy( p_aout_buffer->p_buffer, p_buffer_out, i_buffer_out );
\r
589 /* Date management */
\r
590 p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
\r
591 p_aout_buffer->end_date =
\r
592 aout_DateIncrement( &p_sys->end_date, i_samples );
\r
594 p_out->vt->Release( (IUnknown *)p_out );
\r
596 return p_aout_buffer;
\r
602 static void CopyPicture( decoder_t *p_dec, picture_t *p_pic, uint8_t *p_in )
\r
604 int i_plane, i_line, i_width, i_dst_stride;
\r
605 uint8_t *p_dst, *p_src = p_in;
\r
607 p_dst = p_pic->p[1].p_pixels;
\r
608 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
\r
609 p_pic->p[2].p_pixels = p_dst;
\r
611 for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
\r
613 p_dst = p_pic->p[i_plane].p_pixels;
\r
614 i_width = p_pic->p[i_plane].i_visible_pitch;
\r
615 i_dst_stride = p_pic->p[i_plane].i_pitch;
\r
617 for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
\r
619 p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width );
\r
621 p_dst += i_dst_stride;
\r
625 p_dst = p_pic->p[1].p_pixels;
\r
626 p_pic->p[1].p_pixels = p_pic->p[2].p_pixels;
\r
627 p_pic->p[2].p_pixels = p_dst;
\r