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.
27 #include "vd_internal.h"
29 #include "ffmpeg_files/intreadwrite.h"
31 static const vd_info_t info
= {
36 "Theora project's VP3 codec"
41 #include <theora/theora.h>
43 #define THEORA_NUM_HEADER_PACKETS 3
45 typedef struct theora_struct_st
{
51 /** Convert Theora pixelformat to the corresponding IMGFMT_ */
52 static uint32_t theora_pixelformat2imgfmt(theora_pixelformat fmt
){
54 case OC_PF_420
: return IMGFMT_YV12
;
55 case OC_PF_422
: return IMGFMT_422P
;
56 case OC_PF_444
: return IMGFMT_444P
;
61 // to set/get/query special features/parameters
62 static int control(sh_video_t
*sh
,int cmd
,void* arg
,...){
63 theora_struct_t
*context
= sh
->context
;
65 case VDCTRL_QUERY_FORMAT
:
66 if (*(int*)arg
== theora_pixelformat2imgfmt(context
->inf
.pixelformat
))
71 return CONTROL_UNKNOWN
;
77 static int init(sh_video_t
*sh
){
78 theora_struct_t
*context
= NULL
;
79 uint8_t *extradata
= (uint8_t *)(sh
->bih
+ 1);
80 int extradata_size
= sh
->bih
->biSize
- sizeof(*sh
->bih
);
85 context
= calloc (sizeof (theora_struct_t
), 1);
86 sh
->context
= context
;
90 theora_info_init(&context
->inf
);
91 theora_comment_init(&context
->cc
);
93 /* Read all header packets, pass them to theora_decode_header. */
94 for (i
= 0; i
< THEORA_NUM_HEADER_PACKETS
; i
++)
96 if (extradata_size
> 2) {
97 op
.bytes
= AV_RB16(extradata
);
98 op
.packet
= extradata
+ 2;
100 if (extradata_size
< op
.bytes
+ 2) {
101 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Theora header too small\n");
104 extradata
+= op
.bytes
+ 2;
105 extradata_size
-= op
.bytes
+ 2;
107 op
.bytes
= ds_get_packet (sh
->ds
, &op
.packet
);
111 if ( (errorCode
= theora_decode_header (&context
->inf
, &context
->cc
, &op
)) )
113 mp_msg(MSGT_DECVIDEO
, MSGL_ERR
, "Broken Theora header; errorCode=%i!\n", errorCode
);
119 errorCode
= theora_decode_init (&context
->st
, &context
->inf
);
122 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Theora decode init failed: %i \n", errorCode
);
126 if(sh
->aspect
==0.0 && context
->inf
.aspect_denominator
!=0)
128 sh
->aspect
= ((double)context
->inf
.aspect_numerator
* context
->inf
.width
)/
129 ((double)context
->inf
.aspect_denominator
* context
->inf
.height
);
132 mp_msg(MSGT_DECVIDEO
,MSGL_V
,"INFO: Theora video init ok!\n");
133 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
);
135 return mpcodecs_config_vo (sh
,context
->inf
.width
,context
->inf
.height
,theora_pixelformat2imgfmt(context
->inf
.pixelformat
));
146 static void uninit(sh_video_t
*sh
)
148 theora_struct_t
*context
= sh
->context
;
152 theora_info_clear(&context
->inf
);
153 theora_comment_clear(&context
->cc
);
154 theora_clear (&context
->st
);
162 static mp_image_t
* decode(sh_video_t
*sh
,void* data
,int len
,int flags
)
164 theora_struct_t
*context
= sh
->context
;
174 memset (&op
, 0, sizeof (op
));
179 errorCode
= theora_decode_packetin (&context
->st
, &op
);
182 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Theora decode packetin failed: %i \n",
187 errorCode
= theora_decode_YUVout (&context
->st
, &yuv
);
190 mp_msg(MSGT_DECVIDEO
,MSGL_ERR
,"Theora decode YUVout failed: %i \n",
195 mpi
= mpcodecs_get_image(sh
, MP_IMGTYPE_EXPORT
, 0, yuv
.y_width
, yuv
.y_height
);
196 if(!mpi
) return NULL
;
198 mpi
->planes
[0]=yuv
.y
;
199 mpi
->stride
[0]=yuv
.y_stride
;
200 mpi
->planes
[1]=yuv
.u
;
201 mpi
->stride
[1]=yuv
.uv_stride
;
202 mpi
->planes
[2]=yuv
.v
;
203 mpi
->stride
[2]=yuv
.uv_stride
;