2 * This file is part of MPlayer.
4 * MPlayer is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * MPlayer is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include "vd_internal.h"
30 #include "libavutil/intreadwrite.h"
32 static const vd_info_t info
= {
37 "Theora project's VP3 codec"
42 #include <theora/theora.h>
44 #define THEORA_NUM_HEADER_PACKETS 3
46 typedef struct theora_struct_st
{
52 /** Convert Theora pixelformat to the corresponding IMGFMT_ */
53 static uint32_t theora_pixelformat2imgfmt(theora_pixelformat fmt
){
55 case OC_PF_420
: return IMGFMT_YV12
;
56 case OC_PF_422
: return IMGFMT_422P
;
57 case OC_PF_444
: return IMGFMT_444P
;
62 // to set/get/query special features/parameters
63 static int control(sh_video_t
*sh
,int cmd
,void* arg
,...){
64 theora_struct_t
*context
= sh
->context
;
66 case VDCTRL_QUERY_FORMAT
:
67 if (*(int*)arg
== theora_pixelformat2imgfmt(context
->inf
.pixelformat
))
72 return CONTROL_UNKNOWN
;
78 static int init(sh_video_t
*sh
){
79 theora_struct_t
*context
= NULL
;
80 uint8_t *extradata
= (uint8_t *)(sh
->bih
+ 1);
81 int extradata_size
= sh
->bih
->biSize
- sizeof(*sh
->bih
);
86 context
= calloc (sizeof (theora_struct_t
), 1);
87 sh
->context
= context
;
91 theora_info_init(&context
->inf
);
92 theora_comment_init(&context
->cc
);
94 /* Read all header packets, pass them to theora_decode_header. */
95 for (i
= 0; i
< THEORA_NUM_HEADER_PACKETS
; i
++)
97 if (extradata_size
> 2) {
98 op
.bytes
= AV_RB16(extradata
);
99 op
.packet
= extradata
+ 2;
101 if (extradata_size
< op
.bytes
+ 2) {
102 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Theora header too small\n");
105 extradata
+= op
.bytes
+ 2;
106 extradata_size
-= op
.bytes
+ 2;
108 op
.bytes
= ds_get_packet (sh
->ds
, &op
.packet
);
112 if ( (errorCode
= theora_decode_header (&context
->inf
, &context
->cc
, &op
)) )
114 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Broken Theora header; errorCode=%i!\n", errorCode
);
120 errorCode
= theora_decode_init (&context
->st
, &context
->inf
);
123 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Theora decode init failed: %i \n", errorCode
);
127 if(sh
->aspect
==0.0 && context
->inf
.aspect_denominator
!=0)
129 sh
->aspect
= ((double)context
->inf
.aspect_numerator
* context
->inf
.width
)/
130 ((double)context
->inf
.aspect_denominator
* context
->inf
.height
);
133 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"INFO: Theora video init ok!\n");
134 mp_msg(MSGT_DECVIDEO
,MSGL_INFO
,"Frame: %dx%d, Picture %dx%d, Offset [%d,%d]\n", context
->inf
.width
, context
->inf
.height
, context
->inf
.frame_width
, context
->inf
.frame_height
, context
->inf
.offset_x
, context
->inf
.offset_y
);
136 return mpcodecs_config_vo (sh
,context
->inf
.width
,context
->inf
.height
,theora_pixelformat2imgfmt(context
->inf
.pixelformat
));
147 static void uninit(sh_video_t
*sh
)
149 theora_struct_t
*context
= sh
->context
;
153 theora_info_clear(&context
->inf
);
154 theora_comment_clear(&context
->cc
);
155 theora_clear (&context
->st
);
163 static mp_image_t
* decode(sh_video_t
*sh
,void* data
,int len
,int flags
)
165 theora_struct_t
*context
= sh
->context
;
175 memset (&op
, 0, sizeof (op
));
180 errorCode
= theora_decode_packetin (&context
->st
, &op
);
183 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Theora decode packetin failed: %i \n",
188 errorCode
= theora_decode_YUVout (&context
->st
, &yuv
);
191 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Theora decode YUVout failed: %i \n",
196 mpi
= mpcodecs_get_image(sh
, MP_IMGTYPE_EXPORT
, 0, yuv
.y_width
, yuv
.y_height
);
197 if(!mpi
) return NULL
;
199 mpi
->planes
[0]=yuv
.y
;
200 mpi
->stride
[0]=yuv
.y_stride
;
201 mpi
->planes
[1]=yuv
.u
;
202 mpi
->stride
[1]=yuv
.uv_stride
;
203 mpi
->planes
[2]=yuv
.v
;
204 mpi
->stride
[2]=yuv
.uv_stride
;