1 /*****************************************************************************
2 * vout_pictures.c : picture management functions
3 *****************************************************************************
4 * Copyright (C) 2000-2004 the VideoLAN team
7 * Authors: Vincent Seguin <seguin@via.ecp.fr>
8 * Samuel Hocevar <sam@zoy.org>
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.
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.
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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
34 #include <vlc_common.h>
38 #include <vlc_filter.h>
39 #include <vlc_image.h>
40 #include <vlc_block.h>
42 #include "vout_pictures.h"
43 #include "vout_internal.h"
48 * Remove the reservation flag of a picture, which will cause it to be ready
51 void vout_DisplayPicture( vout_thread_t *p_vout, picture_t *p_pic )
53 vlc_mutex_lock( &p_vout->picture_lock );
55 if( p_pic->i_status == RESERVED_PICTURE )
57 p_pic->i_status = READY_PICTURE;
58 vlc_cond_signal( &p_vout->p->picture_wait );
62 msg_Err( p_vout, "picture to display %p has invalid status %d",
63 p_pic, p_pic->i_status );
65 p_vout->p->i_picture_qtype = p_pic->i_qtype;
67 vlc_mutex_unlock( &p_vout->picture_lock );
71 * Allocate a picture in the video output heap.
73 * This function creates a reserved image in the video output heap.
74 * A null pointer is returned if the function fails. This method provides an
75 * already allocated zone of memory in the picture data fields.
76 * It needs locking since several pictures can be created by several producers
79 int vout_CountPictureAvailable( vout_thread_t *p_vout )
84 vlc_mutex_lock( &p_vout->picture_lock );
85 for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
87 picture_t *p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1) % I_RENDERPICTURES];
89 switch( p_pic->i_status )
91 case DESTROYED_PICTURE:
103 vlc_mutex_unlock( &p_vout->picture_lock );
108 picture_t *vout_CreatePicture( vout_thread_t *p_vout,
110 bool b_top_field_first,
111 unsigned int i_nb_fields )
113 int i_pic; /* picture index */
115 picture_t * p_freepic = NULL; /* first free picture */
118 vlc_mutex_lock( &p_vout->picture_lock );
121 * Look for an empty place in the picture heap.
123 for( i_pic = 0; i_pic < I_RENDERPICTURES; i_pic++ )
125 p_pic = PP_RENDERPICTURE[(p_vout->render.i_last_used_pic + i_pic + 1)
128 switch( p_pic->i_status )
130 case DESTROYED_PICTURE:
131 /* Memory will not be reallocated, and function can end
132 * immediately - this is the best possible case, since no
133 * memory allocation needs to be done */
134 p_pic->i_status = RESERVED_PICTURE;
135 p_pic->i_refcount = 0;
138 p_pic->b_progressive = b_progressive;
139 p_pic->i_nb_fields = i_nb_fields;
140 p_pic->b_top_field_first = b_top_field_first;
142 p_vout->i_heap_size++;
143 p_vout->render.i_last_used_pic =
144 ( p_vout->render.i_last_used_pic + i_pic + 1 )
146 vlc_mutex_unlock( &p_vout->picture_lock );
150 /* Picture is empty and ready for allocation */
151 p_vout->render.i_last_used_pic =
152 ( p_vout->render.i_last_used_pic + i_pic + 1 )
165 if( p_freepic != NULL )
167 vout_AllocatePicture( VLC_OBJECT(p_vout),
168 p_freepic, p_vout->render.i_chroma,
169 p_vout->render.i_width, p_vout->render.i_height,
170 p_vout->render.i_aspect );
172 if( p_freepic->i_planes )
174 /* Copy picture information, set some default values */
175 p_freepic->i_status = RESERVED_PICTURE;
176 p_freepic->i_type = MEMORY_PICTURE;
177 p_freepic->b_slow = 0;
179 p_freepic->i_refcount = 0;
180 p_freepic->b_force = 0;
182 p_freepic->b_progressive = b_progressive;
183 p_freepic->i_nb_fields = i_nb_fields;
184 p_freepic->b_top_field_first = b_top_field_first;
186 p_vout->i_heap_size++;
190 /* Memory allocation failed : set picture as empty */
191 p_freepic->i_status = FREE_PICTURE;
194 msg_Err( p_vout, "picture allocation failed" );
197 vlc_mutex_unlock( &p_vout->picture_lock );
202 /* No free or destroyed picture could be found, but the decoder
203 * will try again in a while. */
204 vlc_mutex_unlock( &p_vout->picture_lock );
210 static void DestroyPicture( vout_thread_t *p_vout, picture_t *p_picture )
212 vlc_assert_locked( &p_vout->picture_lock );
214 p_picture->i_status = DESTROYED_PICTURE;
215 p_vout->i_heap_size--;
216 picture_CleanupQuant( p_picture );
218 vlc_cond_signal( &p_vout->p->picture_wait );
222 * Remove a permanent or reserved picture from the heap
224 * This function frees a previously reserved picture or a permanent
225 * picture. It is meant to be used when the construction of a picture aborted.
226 * Note that the picture will be destroyed even if it is linked !
228 * TODO remove it, vout_DropPicture should be used instead
230 void vout_DestroyPicture( vout_thread_t *p_vout, picture_t *p_pic )
233 /* Check if picture status is valid */
234 vlc_mutex_lock( &p_vout->picture_lock );
235 if( p_pic->i_status != RESERVED_PICTURE )
237 msg_Err( p_vout, "picture to destroy %p has invalid status %d",
238 p_pic, p_pic->i_status );
240 vlc_mutex_unlock( &p_vout->picture_lock );
243 vout_DropPicture( p_vout, p_pic );
247 void vout_UsePictureLocked( vout_thread_t *p_vout, picture_t *p_picture )
249 vlc_assert_locked( &p_vout->picture_lock );
250 if( p_picture->i_refcount > 0 )
252 /* Pretend we displayed the picture, but don't destroy
253 * it since the decoder might still need it. */
254 p_picture->i_status = DISPLAYED_PICTURE;
258 /* Destroy the picture without displaying it */
259 DestroyPicture( p_vout, p_picture );
264 void vout_DropPicture( vout_thread_t *p_vout, picture_t *p_pic )
266 vlc_mutex_lock( &p_vout->picture_lock );
268 if( p_pic->i_status == READY_PICTURE )
270 /* Grr cannot destroy ready picture by myself so be sure vout won't like it */
272 vlc_cond_signal( &p_vout->p->picture_wait );
276 vout_UsePictureLocked( p_vout, p_pic );
279 vlc_mutex_unlock( &p_vout->picture_lock );
283 * Increment reference counter of a picture
285 * This function increments the reference counter of a picture in the video
286 * heap. It needs a lock since several producer threads can access the picture.
288 void vout_LinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
290 vlc_mutex_lock( &p_vout->picture_lock );
292 vlc_mutex_unlock( &p_vout->picture_lock );
296 * Decrement reference counter of a picture
298 * This function decrement the reference counter of a picture in the video heap
300 void vout_UnlinkPicture( vout_thread_t *p_vout, picture_t *p_pic )
302 vlc_mutex_lock( &p_vout->picture_lock );
304 if( p_pic->i_refcount > 0 )
307 msg_Err( p_vout, "Invalid picture reference count (%p, %d)",
308 p_pic, p_pic->i_refcount );
310 if( p_pic->i_refcount == 0 && p_pic->i_status == DISPLAYED_PICTURE )
311 DestroyPicture( p_vout, p_pic );
313 vlc_mutex_unlock( &p_vout->picture_lock );
316 static int vout_LockPicture( vout_thread_t *p_vout, picture_t *p_picture )
318 if( p_picture->pf_lock )
319 return p_picture->pf_lock( p_vout, p_picture );
322 static void vout_UnlockPicture( vout_thread_t *p_vout, picture_t *p_picture )
324 if( p_picture->pf_unlock )
325 p_picture->pf_unlock( p_vout, p_picture );
331 * This function chooses whether the current picture needs to be copied
332 * before rendering, does the subpicture magic, and tells the video output
333 * thread which direct buffer needs to be displayed.
335 picture_t *vout_RenderPicture( vout_thread_t *p_vout, picture_t *p_pic,
336 subpicture_t *p_subpic, bool b_paused )
341 if( p_pic->i_type == DIRECT_PICTURE )
343 /* Picture is in a direct buffer. */
345 if( p_subpic != NULL )
347 /* We have subtitles. First copy the picture to
348 * the spare direct buffer, then render the
350 if( vout_LockPicture( p_vout, PP_OUTPUTPICTURE[0] ) )
353 picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
355 spu_RenderSubpictures( p_vout->p_spu,
356 PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
357 p_subpic, &p_vout->fmt_in, b_paused );
359 vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
361 return PP_OUTPUTPICTURE[0];
364 /* No subtitles, picture is in a directbuffer so
365 * we can display it directly (even if it is still
370 /* Not a direct buffer. We either need to copy it to a direct buffer,
371 * or render it if the chroma isn't the same. */
372 if( p_vout->p->b_direct )
374 /* Picture is not in a direct buffer, but is exactly the
375 * same size as the direct buffers. A memcpy() is enough,
376 * then render the subtitles. */
378 if( vout_LockPicture( p_vout, PP_OUTPUTPICTURE[0] ) )
381 picture_Copy( PP_OUTPUTPICTURE[0], p_pic );
382 spu_RenderSubpictures( p_vout->p_spu,
383 PP_OUTPUTPICTURE[0], &p_vout->fmt_out,
384 p_subpic, &p_vout->fmt_in, b_paused );
386 vout_UnlockPicture( p_vout, PP_OUTPUTPICTURE[0] );
388 return PP_OUTPUTPICTURE[0];
391 /* Picture is not in a direct buffer, and needs to be converted to
392 * another size/chroma. Then the subtitles need to be rendered as
393 * well. This usually means software YUV, or hardware YUV with a
394 * different chroma. */
396 if( p_subpic != NULL && p_vout->p_picture[0].b_slow )
398 /* The picture buffer is in slow memory. We'll use
399 * the "2 * VOUT_MAX_PICTURES + 1" picture as a temporary
400 * one for subpictures rendering. */
401 picture_t *p_tmp_pic = &p_vout->p_picture[2 * VOUT_MAX_PICTURES];
402 if( p_tmp_pic->i_status == FREE_PICTURE )
404 vout_AllocatePicture( VLC_OBJECT(p_vout),
405 p_tmp_pic, p_vout->fmt_out.i_chroma,
406 p_vout->fmt_out.i_width,
407 p_vout->fmt_out.i_height,
408 p_vout->fmt_out.i_aspect );
409 p_tmp_pic->i_type = MEMORY_PICTURE;
410 p_tmp_pic->i_status = RESERVED_PICTURE;
411 /* some modules (such as blend) needs to know the extra information in picture heap */
412 p_tmp_pic->p_heap = &p_vout->output;
415 /* Convert image to the first direct buffer */
416 p_vout->p->p_chroma->p_owner = (filter_owner_sys_t *)p_tmp_pic;
417 p_vout->p->p_chroma->pf_video_filter( p_vout->p->p_chroma, p_pic );
419 /* Render subpictures on the first direct buffer */
420 spu_RenderSubpictures( p_vout->p_spu,
421 p_tmp_pic, &p_vout->fmt_out,
422 p_subpic, &p_vout->fmt_in, b_paused );
424 if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
427 picture_Copy( &p_vout->p_picture[0], p_tmp_pic );
431 if( vout_LockPicture( p_vout, &p_vout->p_picture[0] ) )
434 /* Convert image to the first direct buffer */
435 p_vout->p->p_chroma->p_owner = (filter_owner_sys_t *)&p_vout->p_picture[0];
436 p_vout->p->p_chroma->pf_video_filter( p_vout->p->p_chroma, p_pic );
438 /* Render subpictures on the first direct buffer */
439 spu_RenderSubpictures( p_vout->p_spu,
440 &p_vout->p_picture[0], &p_vout->fmt_out,
441 p_subpic, &p_vout->fmt_in, b_paused );
444 vout_UnlockPicture( p_vout, &p_vout->p_picture[0] );
446 return &p_vout->p_picture[0];
450 * Calculate image window coordinates
452 * This function will be accessed by plugins. It calculates the relative
453 * position of the output window and the image window.
455 void vout_PlacePicture( const vout_thread_t *p_vout,
456 unsigned int i_width, unsigned int i_height,
457 unsigned int *restrict pi_x,
458 unsigned int *restrict pi_y,
459 unsigned int *restrict pi_width,
460 unsigned int *restrict pi_height )
462 if( i_width <= 0 || i_height <= 0 )
464 *pi_width = *pi_height = *pi_x = *pi_y = 0;
468 if( p_vout->b_autoscale )
471 *pi_height = i_height;
475 int i_zoom = p_vout->i_zoom;
476 /* be realistic, scaling factor confined between .2 and 10. */
477 if( i_zoom > 10 * ZOOM_FP_FACTOR ) i_zoom = 10 * ZOOM_FP_FACTOR;
478 else if( i_zoom < ZOOM_FP_FACTOR / 5 ) i_zoom = ZOOM_FP_FACTOR / 5;
480 unsigned int i_original_width, i_original_height;
482 if( p_vout->fmt_in.i_sar_num >= p_vout->fmt_in.i_sar_den )
484 i_original_width = p_vout->fmt_in.i_visible_width *
485 p_vout->fmt_in.i_sar_num / p_vout->fmt_in.i_sar_den;
486 i_original_height = p_vout->fmt_in.i_visible_height;
490 i_original_width = p_vout->fmt_in.i_visible_width;
491 i_original_height = p_vout->fmt_in.i_visible_height *
492 p_vout->fmt_in.i_sar_den / p_vout->fmt_in.i_sar_num;
495 /* On windows, inner video window exceeding container leads to black screen */
496 *pi_width = __MIN( i_width, i_original_width * i_zoom / ZOOM_FP_FACTOR );
497 *pi_height = __MIN( i_height, i_original_height * i_zoom / ZOOM_FP_FACTOR );
499 *pi_width = i_original_width * i_zoom / ZOOM_FP_FACTOR ;
500 *pi_height = i_original_height * i_zoom / ZOOM_FP_FACTOR ;
504 int64_t i_scaled_width = p_vout->fmt_in.i_visible_width * (int64_t)p_vout->fmt_in.i_sar_num *
505 *pi_height / p_vout->fmt_in.i_visible_height / p_vout->fmt_in.i_sar_den;
506 int64_t i_scaled_height = p_vout->fmt_in.i_visible_height * (int64_t)p_vout->fmt_in.i_sar_den *
507 *pi_width / p_vout->fmt_in.i_visible_width / p_vout->fmt_in.i_sar_num;
509 if( i_scaled_width <= 0 || i_scaled_height <= 0 )
511 msg_Warn( p_vout, "ignoring broken aspect ratio" );
512 i_scaled_width = *pi_width;
513 i_scaled_height = *pi_height;
516 if( i_scaled_width > *pi_width )
517 *pi_height = i_scaled_height;
519 *pi_width = i_scaled_width;
521 switch( p_vout->i_alignment & VOUT_ALIGN_HMASK )
523 case VOUT_ALIGN_LEFT:
526 case VOUT_ALIGN_RIGHT:
527 *pi_x = i_width - *pi_width;
530 *pi_x = ( i_width - *pi_width ) / 2;
533 switch( p_vout->i_alignment & VOUT_ALIGN_VMASK )
538 case VOUT_ALIGN_BOTTOM:
539 *pi_y = i_height - *pi_height;
542 *pi_y = ( i_height - *pi_height ) / 2;
547 * Allocate a new picture in the heap.
549 * This function allocates a fake direct buffer in memory, which can be
550 * used exactly like a video buffer. The video output thread then manages
551 * how it gets displayed.
553 int __vout_AllocatePicture( vlc_object_t *p_this, picture_t *p_pic,
554 vlc_fourcc_t i_chroma,
555 int i_width, int i_height, int i_aspect )
557 int i_bytes, i_index, i_width_aligned, i_height_aligned;
559 /* Make sure the real dimensions are a multiple of 16 */
560 i_width_aligned = (i_width + 15) >> 4 << 4;
561 i_height_aligned = (i_height + 15) >> 4 << 4;
563 if( vout_InitPicture( p_this, p_pic, i_chroma,
564 i_width, i_height, i_aspect ) != VLC_SUCCESS )
570 /* Calculate how big the new image should be */
571 i_bytes = p_pic->format.i_bits_per_pixel *
572 i_width_aligned * i_height_aligned / 8;
574 p_pic->p_data = vlc_memalign( &p_pic->p_data_orig, 16, i_bytes );
576 if( p_pic->p_data == NULL )
582 /* Fill the p_pixels field for each plane */
583 p_pic->p[ 0 ].p_pixels = p_pic->p_data;
585 for( i_index = 1; i_index < p_pic->i_planes; i_index++ )
587 p_pic->p[i_index].p_pixels = p_pic->p[i_index-1].p_pixels +
588 p_pic->p[i_index-1].i_lines * p_pic->p[i_index-1].i_pitch;
595 * Initialise the video format fields given chroma/size.
597 * This function initializes all the video_frame_format_t fields given the
598 * static properties of a picture (chroma and size).
599 * \param p_format Pointer to the format structure to initialize
600 * \param i_chroma Chroma to set
601 * \param i_width Width to set
602 * \param i_height Height to set
603 * \param i_aspect Aspect ratio
605 void vout_InitFormat( video_frame_format_t *p_format, vlc_fourcc_t i_chroma,
606 int i_width, int i_height, int i_aspect )
608 p_format->i_chroma = i_chroma;
609 p_format->i_width = p_format->i_visible_width = i_width;
610 p_format->i_height = p_format->i_visible_height = i_height;
611 p_format->i_x_offset = p_format->i_y_offset = 0;
612 p_format->i_aspect = i_aspect;
615 /* Assume we have square pixels */
616 if( i_width && i_height )
617 p_format->i_aspect = i_width * VOUT_ASPECT_FACTOR / i_height;
619 p_format->i_aspect = 0;
625 p_format->i_bits_per_pixel = 32;
629 p_format->i_bits_per_pixel = 24;
635 p_format->i_bits_per_pixel = 16;
639 p_format->i_bits_per_pixel = 16;
646 p_format->i_bits_per_pixel = 12;
650 p_format->i_bits_per_pixel = 9;
653 p_format->i_bits_per_pixel = 8;
656 p_format->i_bits_per_pixel = 8;
661 p_format->i_bits_per_pixel = 32;
664 p_format->i_bits_per_pixel = 24;
668 p_format->i_bits_per_pixel = 16;
671 p_format->i_bits_per_pixel = 8;
678 p_format->i_bits_per_pixel = 8;
682 p_format->i_bits_per_pixel = 0;
688 * Initialise the picture_t fields given chroma/size.
690 * This function initializes most of the picture_t fields given a chroma and
691 * size. It makes the assumption that stride == width.
692 * \param p_this The calling object
693 * \param p_pic Pointer to the picture to initialize
694 * \param i_chroma The chroma fourcc to set
695 * \param i_width The width of the picture
696 * \param i_height The height of the picture
697 * \param i_aspect The aspect ratio of the picture
699 int __vout_InitPicture( vlc_object_t *p_this, picture_t *p_pic,
700 vlc_fourcc_t i_chroma,
701 int i_width, int i_height, int i_aspect )
703 int i_index, i_width_aligned, i_height_aligned;
705 /* Store default values */
706 for( i_index = 0; i_index < VOUT_MAX_PLANES; i_index++ )
708 p_pic->p[i_index].p_pixels = NULL;
709 p_pic->p[i_index].i_pixel_pitch = 1;
712 p_pic->pf_release = NULL;
713 p_pic->pf_lock = NULL;
714 p_pic->pf_unlock = NULL;
715 p_pic->i_refcount = 0;
717 p_pic->i_qtype = QTYPE_NONE;
718 p_pic->i_qstride = 0;
721 vout_InitFormat( &p_pic->format, i_chroma, i_width, i_height, i_aspect );
723 /* Make sure the real dimensions are a multiple of 16 */
724 i_width_aligned = (i_width + 15) >> 4 << 4;
725 i_height_aligned = (i_height + 15) >> 4 << 4;
727 /* Calculate coordinates */
731 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
732 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
733 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
734 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
735 p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
736 p_pic->p[ U_PLANE ].i_visible_lines = i_height;
737 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
738 p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
739 p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
740 p_pic->p[ V_PLANE ].i_visible_lines = i_height;
741 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
742 p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
748 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
749 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
750 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
751 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
752 p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 4;
753 p_pic->p[ U_PLANE ].i_visible_lines = i_height / 4;
754 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 4;
755 p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 4;
756 p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 4;
757 p_pic->p[ V_PLANE ].i_visible_lines = i_height / 4;
758 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 4;
759 p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 4;
767 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
768 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
769 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
770 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
771 p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
772 p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
773 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
774 p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
775 p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
776 p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
777 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 2;
778 p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 2;
784 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
785 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
786 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
787 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
788 p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
789 p_pic->p[ U_PLANE ].i_visible_lines = i_height;
790 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned / 2;
791 p_pic->p[ U_PLANE ].i_visible_pitch = i_width / 2;
792 p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
793 p_pic->p[ V_PLANE ].i_visible_lines = i_height;
794 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned / 2;
795 p_pic->p[ V_PLANE ].i_visible_pitch = i_width / 2;
801 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
802 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
803 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
804 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
805 p_pic->p[ U_PLANE ].i_lines = i_height_aligned / 2;
806 p_pic->p[ U_PLANE ].i_visible_lines = i_height / 2;
807 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
808 p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
809 p_pic->p[ V_PLANE ].i_lines = i_height_aligned / 2;
810 p_pic->p[ V_PLANE ].i_visible_lines = i_height / 2;
811 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
812 p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
818 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
819 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
820 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
821 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
822 p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
823 p_pic->p[ U_PLANE ].i_visible_lines = i_height;
824 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
825 p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
826 p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
827 p_pic->p[ V_PLANE ].i_visible_lines = i_height;
828 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
829 p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
834 p_pic->p[ Y_PLANE ].i_lines = i_height_aligned;
835 p_pic->p[ Y_PLANE ].i_visible_lines = i_height;
836 p_pic->p[ Y_PLANE ].i_pitch = i_width_aligned;
837 p_pic->p[ Y_PLANE ].i_visible_pitch = i_width;
838 p_pic->p[ U_PLANE ].i_lines = i_height_aligned;
839 p_pic->p[ U_PLANE ].i_visible_lines = i_height;
840 p_pic->p[ U_PLANE ].i_pitch = i_width_aligned;
841 p_pic->p[ U_PLANE ].i_visible_pitch = i_width;
842 p_pic->p[ V_PLANE ].i_lines = i_height_aligned;
843 p_pic->p[ V_PLANE ].i_visible_lines = i_height;
844 p_pic->p[ V_PLANE ].i_pitch = i_width_aligned;
845 p_pic->p[ V_PLANE ].i_visible_pitch = i_width;
846 p_pic->p[ A_PLANE ].i_lines = i_height_aligned;
847 p_pic->p[ A_PLANE ].i_visible_lines = i_height;
848 p_pic->p[ A_PLANE ].i_pitch = i_width_aligned;
849 p_pic->p[ A_PLANE ].i_visible_pitch = i_width;
854 p_pic->p->i_lines = i_height_aligned;
855 p_pic->p->i_visible_lines = i_height;
856 p_pic->p->i_pitch = i_width_aligned;
857 p_pic->p->i_visible_pitch = i_width;
858 p_pic->p->i_pixel_pitch = 8;
863 p_pic->p->i_lines = i_height_aligned;
864 p_pic->p->i_visible_lines = i_height;
865 p_pic->p->i_pitch = i_width_aligned;
866 p_pic->p->i_visible_pitch = i_width;
867 p_pic->p->i_pixel_pitch = 4;
873 p_pic->p->i_lines = i_height_aligned;
874 p_pic->p->i_visible_lines = i_height;
875 p_pic->p->i_pitch = i_width_aligned * 2;
876 p_pic->p->i_visible_pitch = i_width * 2;
877 p_pic->p->i_pixel_pitch = 4;
882 p_pic->p->i_lines = i_height_aligned;
883 p_pic->p->i_visible_lines = i_height;
884 p_pic->p->i_pitch = i_width_aligned;
885 p_pic->p->i_visible_pitch = i_width;
886 p_pic->p->i_pixel_pitch = 1;
891 p_pic->p->i_lines = i_height_aligned;
892 p_pic->p->i_visible_lines = i_height;
893 p_pic->p->i_pitch = i_width_aligned * 2;
894 p_pic->p->i_visible_pitch = i_width * 2;
895 p_pic->p->i_pixel_pitch = 2;
900 p_pic->p->i_lines = i_height_aligned;
901 p_pic->p->i_visible_lines = i_height;
902 p_pic->p->i_pitch = i_width_aligned * 2;
903 p_pic->p->i_visible_pitch = i_width * 2;
904 p_pic->p->i_pixel_pitch = 2;
909 p_pic->p->i_lines = i_height_aligned;
910 p_pic->p->i_visible_lines = i_height;
911 p_pic->p->i_pitch = i_width_aligned * 3;
912 p_pic->p->i_visible_pitch = i_width * 3;
913 p_pic->p->i_pixel_pitch = 3;
919 p_pic->p->i_lines = i_height_aligned;
920 p_pic->p->i_visible_lines = i_height;
921 p_pic->p->i_pitch = i_width_aligned * 4;
922 p_pic->p->i_visible_pitch = i_width * 4;
923 p_pic->p->i_pixel_pitch = 4;
931 p_pic->p->i_lines = i_height_aligned;
932 p_pic->p->i_visible_lines = i_height;
933 p_pic->p->i_pitch = i_width_aligned;
934 p_pic->p->i_visible_pitch = i_width;
935 p_pic->p->i_pixel_pitch = 1;
941 msg_Err( p_this, "unknown chroma type 0x%.8x (%4.4s)",
942 i_chroma, (char*)&i_chroma );
951 * Compare two chroma values
953 * This function returns 1 if the two fourcc values given as argument are
954 * the same format (eg. UYVY/UYNV) or almost the same format (eg. I420/YV12)
956 int vout_ChromaCmp( vlc_fourcc_t i_chroma, vlc_fourcc_t i_amorhc )
958 static const vlc_fourcc_t p_I420[] = {
959 FOURCC_I420, FOURCC_IYUV, FOURCC_YV12, FOURCC_J420, 0
961 static const vlc_fourcc_t p_I422[] = {
962 FOURCC_I422, FOURCC_J422, 0
964 static const vlc_fourcc_t p_I440[] = {
965 FOURCC_I440, FOURCC_J440, 0
967 static const vlc_fourcc_t p_I444[] = {
968 FOURCC_I444, FOURCC_J444, 0
970 static const vlc_fourcc_t p_UYVY[] = {
971 FOURCC_UYVY, FOURCC_UYNV, FOURCC_Y422, 0
973 static const vlc_fourcc_t p_YUYV[] = {
974 FOURCC_YUY2, FOURCC_YUNV, 0
976 static const vlc_fourcc_t p_GREY[] = {
977 FOURCC_GREY, FOURCC_Y800, FOURCC_Y8, 0
979 static const vlc_fourcc_t *pp_fcc[] = {
980 p_I420, p_I422, p_I440, p_I444, p_UYVY, p_YUYV, p_GREY, NULL
983 /* If they are the same, they are the same ! */
984 if( i_chroma == i_amorhc )
987 /* Check for equivalence classes */
988 for( int i = 0; pp_fcc[i] != NULL; i++ )
992 for( int j = 0; pp_fcc[i][j] != 0; j++ )
994 if( i_chroma == pp_fcc[i][j] )
996 if( i_amorhc == pp_fcc[i][j] )
999 if( b_fcc1 && b_fcc2 )
1005 /*****************************************************************************
1007 *****************************************************************************/
1008 static void PictureReleaseCallback( picture_t *p_picture )
1010 if( --p_picture->i_refcount > 0 )
1012 picture_Delete( p_picture );
1014 /*****************************************************************************
1016 *****************************************************************************/
1017 picture_t *picture_New( vlc_fourcc_t i_chroma, int i_width, int i_height, int i_aspect )
1019 picture_t *p_picture = calloc( 1, sizeof(*p_picture) );
1023 if( __vout_AllocatePicture( NULL, p_picture,
1024 i_chroma, i_width, i_height, i_aspect ) )
1030 p_picture->i_refcount = 1;
1031 p_picture->pf_release = PictureReleaseCallback;
1032 p_picture->i_status = RESERVED_PICTURE;
1037 /*****************************************************************************
1039 *****************************************************************************/
1040 void picture_Delete( picture_t *p_picture )
1042 assert( p_picture && p_picture->i_refcount == 0 );
1044 free( p_picture->p_q );
1045 free( p_picture->p_data_orig );
1046 free( p_picture->p_sys );
1050 /*****************************************************************************
1052 *****************************************************************************/
1053 void picture_CopyPixels( picture_t *p_dst, const picture_t *p_src )
1057 for( i = 0; i < p_src->i_planes ; i++ )
1058 plane_CopyPixels( p_dst->p+i, p_src->p+i );
1061 void plane_CopyPixels( plane_t *p_dst, const plane_t *p_src )
1063 const unsigned i_width = __MIN( p_dst->i_visible_pitch,
1064 p_src->i_visible_pitch );
1065 const unsigned i_height = __MIN( p_dst->i_visible_lines,
1066 p_src->i_visible_lines );
1068 if( p_src->i_pitch == p_dst->i_pitch )
1070 /* There are margins, but with the same width : perfect ! */
1071 vlc_memcpy( p_dst->p_pixels, p_src->p_pixels,
1072 p_src->i_pitch * i_height );
1076 /* We need to proceed line by line */
1077 uint8_t *p_in = p_src->p_pixels;
1078 uint8_t *p_out = p_dst->p_pixels;
1084 for( i_line = i_height; i_line--; )
1086 vlc_memcpy( p_out, p_in, i_width );
1087 p_in += p_src->i_pitch;
1088 p_out += p_dst->i_pitch;
1093 /*****************************************************************************
1095 *****************************************************************************/
1096 int picture_Export( vlc_object_t *p_obj,
1098 video_format_t *p_fmt,
1099 picture_t *p_picture,
1100 vlc_fourcc_t i_format,
1101 int i_override_width, int i_override_height )
1104 video_format_t fmt_in = p_picture->format;
1105 if( fmt_in.i_sar_num <= 0 || fmt_in.i_sar_den <= 0 )
1108 fmt_in.i_sar_den = 1;
1112 video_format_t fmt_out;
1113 memset( &fmt_out, 0, sizeof(fmt_out) );
1115 fmt_out.i_sar_den = 1;
1116 fmt_out.i_chroma = i_format;
1117 fmt_out.i_width = i_override_width;
1118 fmt_out.i_height = i_override_height;
1120 if( fmt_out.i_height == 0 && fmt_out.i_width > 0 )
1122 fmt_out.i_height = fmt_in.i_height * fmt_out.i_width / fmt_in.i_width;
1123 const int i_height = fmt_out.i_height * fmt_in.i_sar_den / fmt_in.i_sar_num;
1125 fmt_out.i_height = i_height;
1129 if( fmt_out.i_width == 0 && fmt_out.i_height > 0 )
1131 fmt_out.i_width = fmt_in.i_width * fmt_out.i_height / fmt_in.i_height;
1135 fmt_out.i_width = fmt_in.i_width;
1136 fmt_out.i_height = fmt_in.i_height;
1138 const int i_width = fmt_out.i_width * fmt_in.i_sar_num / fmt_in.i_sar_den;
1140 fmt_out.i_width = i_width;
1143 image_handler_t *p_image = image_HandlerCreate( p_obj );
1145 block_t *p_block = image_Write( p_image, p_picture, &fmt_in, &fmt_out );
1147 image_HandlerDelete( p_image );
1150 return VLC_EGENERIC;
1153 p_block->i_dts = p_picture->date;
1157 *pp_image = p_block;
1162 /*****************************************************************************
1164 *****************************************************************************/