summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/combined/xine_theora_decoder.c102
1 files changed, 83 insertions, 19 deletions
diff --git a/src/combined/xine_theora_decoder.c b/src/combined/xine_theora_decoder.c
index 27520994d..25e46a52e 100644
--- a/src/combined/xine_theora_decoder.c
+++ b/src/combined/xine_theora_decoder.c
@@ -82,9 +82,10 @@ static void readin_op (theora_decoder_t *this, unsigned char* src, int size) {
this->done=this->done+size;
}
-static void yuv2frame(yuv_buffer *yuv, vo_frame_t *frame, int offset_x, int offset_y) {
- int i;
- int crop_offset;
+static void yuv2frame(yuv_buffer *yuv, vo_frame_t *frame, int offset_x, int offset_y,
+ unsigned pixel_format) {
+ int x, y;
+ int crop_offset_y, crop_offset_c;
/* fixme - direct rendering (exchaning pointers) may be possible.
* frame->base[0] = yuv->y could work if one could change the
@@ -99,21 +100,65 @@ static void yuv2frame(yuv_buffer *yuv, vo_frame_t *frame, int offset_x, int offs
* in the theora header is carried out.
*/
- crop_offset=offset_x+yuv->y_stride*offset_y;
- for(i=0;i<frame->height;i++)
- xine_fast_memcpy(frame->base[0]+frame->pitches[0]*i,
- yuv->y+crop_offset+yuv->y_stride*i,
- frame->width);
-
- crop_offset=(offset_x/2)+(yuv->uv_stride)*(offset_y/2);
- for(i=0;i<frame->height/2;i++){
- xine_fast_memcpy(frame->base[1]+frame->pitches[1]*i,
- yuv->u+crop_offset+yuv->uv_stride*i,
- frame->width/2);
- xine_fast_memcpy(frame->base[2]+frame->pitches[2]*i,
- yuv->v+crop_offset+yuv->uv_stride*i,
- frame->width/2);
+ if (pixel_format == OC_PF_444) {
+ /* downsample */
+ init_yuv_conversion();
+
+ crop_offset_y = offset_x + yuv->y_stride * offset_y;
+ crop_offset_c = offset_x + yuv->uv_stride * offset_y;
+
+ yuv_planes_t yuv_planes;
+ yuv_planes.y = yuv->y + crop_offset_y;
+ yuv_planes.u = yuv->u + crop_offset_c;
+ yuv_planes.v = yuv->v + crop_offset_c;
+ yuv_planes.row_width = frame->width;
+ yuv_planes.row_count = 1;
+
+ for (y = 0; y < frame->height; y++) {
+ yuv444_to_yuy2(&yuv_planes, frame->base[0] + frame->pitches[0] * y, frame->pitches[0]);
+
+ yuv_planes.y += yuv->y_stride;
+ yuv_planes.u += yuv->uv_stride;
+ yuv_planes.v += yuv->uv_stride;
+ }
+ }
+ else if (pixel_format == OC_PF_422) {
+ /* interleave */
+
+ crop_offset_y = offset_x + yuv->y_stride * offset_y;
+ crop_offset_c = offset_x/2 + yuv->uv_stride * offset_y;
+
+ for (y = 0; y < frame->height; y++) {
+ uint8_t *dst = frame->base[0] + frame->pitches[0] * y;
+ uint8_t *src_y = yuv->y + crop_offset_y + yuv->y_stride * y;
+ uint8_t *src_u = yuv->u + crop_offset_c + yuv->uv_stride * y;
+ uint8_t *src_v = yuv->v + crop_offset_c + yuv->uv_stride * y;
+ for (x = 0; x < frame->width/2; x++) {
+ *dst++ = *src_y++;
+ *dst++ = *src_u++;
+ *dst++ = *src_y++;
+ *dst++ = *src_v++;
+ }
+ }
+ } else /*if (pixel_format == OC_PF_420)*/ {
+
+ crop_offset_y = offset_x + yuv->y_stride * offset_y;
+ crop_offset_c = offset_x/2 + yuv->uv_stride * (offset_y/2);
+
+ for (y = 0; y < frame->height; y++)
+ xine_fast_memcpy(frame->base[0] + frame->pitches[0] * y,
+ yuv->y + crop_offset_y + yuv->y_stride * y,
+ frame->width);
+
+ for(y = 0; y < frame->height/2; y++) {
+ xine_fast_memcpy(frame->base[1] + frame->pitches[1] * y,
+ yuv->u + crop_offset_c + yuv->uv_stride * y,
+ frame->width/2);
+ xine_fast_memcpy(frame->base[2] + frame->pitches[2] * y,
+ yuv->v + crop_offset_c + yuv->uv_stride * y,
+ frame->width/2);
+ }
}
}
@@ -239,16 +284,35 @@ static void theora_decode_data (video_decoder_t *this_gen, buf_element_t *buf) {
if ( ret!=0) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "libtheora:Received an bad packet\n");
} else if (!this->skipframes) {
+ int format;
theora_decode_YUVout(&this->t_state,&yuv);
+ /* pixel format */
+ switch (this->t_state.i->pixelformat) {
+ case OC_PF_444:
+ format = XINE_IMGFMT_YUY2;
+ break;
+ case OC_PF_422:
+ format = XINE_IMGFMT_YUY2;
+ break;
+ case OC_PF_420:
+ format = XINE_IMGFMT_YV12;
+ break;
+ default:
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "libtheora: unknown pixel format %u\n",
+ (unsigned)this->t_state.i->pixelformat);
+ format = XINE_IMGFMT_YV12;
+ break;
+ }
+
/*fixme - aspectratio from theora is not considered*/
frame = this->stream->video_out->get_frame( this->stream->video_out,
this->width, this->height,
this->ratio,
- XINE_IMGFMT_YV12,
+ format,
VO_BOTH_FIELDS);
- yuv2frame(&yuv, frame, this->offset_x, this->offset_y);
+ yuv2frame(&yuv, frame, this->offset_x, this->offset_y, this->t_state.i->pixelformat);
frame->pts = buf->pts;
frame->duration=this->frame_duration;