📄 video_out_rgb.c
字号:
"punpckhwd %%mm2, %%mm0\n\t" /* mm0 = [0 b3 g3 r3 0 b2 g2 r2] */ "movq %%mm0, 8(%3)\n\t" "addl $4, %0\n\t" "addl $4, %1\n\t" "addl $4, %2\n\t" "addl $16, %3\n\t" : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer) : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer) : "memory"); } __asm__ __volatile__("emms\n\t"); }#endif while(rest--) { *(buffer) = *(r_data++); *(buffer + 1) = *(g_data++); *(buffer + 2) = *(b_data++); buffer += 4; }}static void__pack_bgr24(rgb_planar_t* data, void* dest, uint32_t pixels, uint32_t accel){ uint8_t* buffer = (uint8_t*) dest; uint8_t* r_data = data->r; uint8_t* g_data = data->g; uint8_t* b_data = data->b; uint32_t rest = pixels;/* MMXEXT doesn't speed up here */#ifdef COMPILE_ASSEMBLY if((accel & MM_MMX) == MM_MMX) { uint32_t n = pixels >> 2; /* (width * height) / 4 */ rest = pixels & 3; /* pixels - (n * 4) */ __asm__ __volatile__( "pxor %%mm3, %%mm3\n\t" ::: "memory"); while(n--) { __asm__ __volatile__( "movd (%0), %%mm0\n\t" /* mm0 = [0 0 0 0 r3 r2 r1 r0] */ "movd (%1), %%mm1\n\t" /* mm1 = [0 0 0 0 g3 g2 g1 g0] */ "movd (%2), %%mm2\n\t" /* mm2 = [0 0 0 0 b3 b2 b1 b0] */ "punpcklbw %%mm1, %%mm0\n\t" /* mm1 = [g3 r3 g2 r2 g1 r1 g0 r0] */ "punpcklbw %%mm3, %%mm2\n\t" /* mm3 = [0 b3 0 b2 0 b1 0 b0] */ "movq %%mm0, %%mm4\n\t" /* mm4 = [g3 r3 g2 r2 g1 r1 g0 r0] */ "punpcklwd %%mm2, %%mm4\n\t" /* mm4 = [0 b1 g1 r1 0 b0 g0 r0] */ "movd %%mm4, (%3)\n\t" "punpckhdq %%mm4, %%mm4\n\t" /* mm4 = [0 b1 g1 r1 0 b1 g1 r1] */ "movd %%mm4, 3(%3)\n\t" "punpckhwd %%mm2, %%mm0\n\t" /* mm2 = [0 b3 g3 r3 0 b2 g2 r2] */ "movd %%mm0, 6(%3)\n\t" "punpckhdq %%mm0, %%mm0\n\t" /* mm2 = [0 b3 g3 r3 0 b3 g3 r3] */ "movd %%mm0, 9(%3)\n\t" "addl $4, %0\n\t" "addl $4, %1\n\t" "addl $4, %2\n\t" "addl $12, %3\n\t" : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer) : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer) : "memory"); } __asm__ __volatile__("emms\n\t"); }#endif while(rest--) { *(buffer) = *(r_data++); *(buffer + 1) = *(g_data++); *(buffer + 2) = *(b_data++); buffer += 3; }}static void__pack_bgr16(rgb_planar_t* data, void* dest, uint32_t pixels, uint32_t accel){ uint16_t* buffer = (uint16_t*) dest; uint8_t* r_data = data->r; uint8_t* g_data = data->g; uint8_t* b_data = data->b; uint32_t rest = pixels;#ifdef COMPILE_ASSEMBLY if((accel & MM_MMXEXT) == MM_MMXEXT) { uint32_t n = pixels >> 2; /* (width * height) / 4 */ rest = pixels & 3; /* pixels - (n * 4) */ __asm__ __volatile__( "pxor %%mm3, %%mm3\n\t" ::: "memory"); while(n--) { __asm__ __volatile__( "prefetchw 320(%0)\n\t" "movd (%0), %%mm0\n\t" /* mm0 = [0 | r3r2r1r0] */ "movd (%1), %%mm1\n\t" /* mm1 = [0 | g3g2g1g0] */ "movd (%2), %%mm2\n\t" /* mm2 = [0 | b3b2b1b0] */ "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */ "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */ "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */ "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */ "psrlw $2, %%mm1\n\t" /* word = [00000000 00gggggg] */ "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */ "psllw $11, %%mm2\n\t" /* word = [bbbbb000 00000000] */ "psllw $5, %%mm1\n\t" /* word = [00000ggg ggg00000] */ "por %%mm2, %%mm1\n\t" /* word = [bbbbbggg ggg00000] */ "por %%mm1, %%mm0\n\t" /* word = [bbbbbggg gggrrrrr] */ "movntq %%mm0, (%3)\n\t" "addl $4, %0\n\t" "addl $4, %1\n\t" "addl $4, %2\n\t" "addl $8, %3\n\t" : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer) : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer) : "memory"); } __asm__ __volatile__("sfence; emms\n\t"); } else if((accel & MM_MMX) == MM_MMX) { uint32_t n = pixels >> 2; /* (width * height) / 4 */ rest = pixels & 3; /* pixels - (n * 4) */ __asm__ __volatile__( "pxor %%mm3, %%mm3\n\t" ::: "memory"); while(n--) { __asm__ __volatile__( "movd (%0), %%mm0\n\t" /* mm0 = [0 | r3r2r1r0] */ "movd (%1), %%mm1\n\t" /* mm1 = [0 | g3g2g1g0] */ "movd (%2), %%mm2\n\t" /* mm2 = [0 | b3b2b1b0] */ "punpcklbw %%mm3, %%mm0\n\t" /* mm0 = [0 r3 0 r2 0 r1 0 r0] */ "punpcklbw %%mm3, %%mm1\n\t" /* mm1 = [0 g3 0 g2 0 g1 0 g0] */ "punpcklbw %%mm3, %%mm2\n\t" /* mm2 = [0 b3 0 b2 0 b1 0 b0] */ "psrlw $3, %%mm0\n\t" /* word = [00000000 000rrrrr] */ "psrlw $2, %%mm1\n\t" /* word = [00000000 00gggggg] */ "psrlw $3, %%mm2\n\t" /* word = [00000000 000bbbbb] */ "psllw $11, %%mm2\n\t" /* word = [bbbbb000 00000000] */ "psllw $5, %%mm1\n\t" /* word = [00000ggg ggg00000] */ "por %%mm2, %%mm1\n\t" /* word = [bbbbbggg ggg00000] */ "por %%mm1, %%mm0\n\t" /* word = [bbbbbggg gggrrrrr] */ "movq %%mm0, (%3)\n\t" "addl $4, %0\n\t" "addl $4, %1\n\t" "addl $4, %2\n\t" "addl $8, %3\n\t" : "=&r" (r_data), "=&r" (g_data), "=&r" (b_data), "=&r" (buffer) : "0" (r_data), "1" (g_data), "2" (b_data), "3" (buffer) : "memory"); } __asm__ __volatile__("emms\n\t"); }#endif while(rest--) { uint16_t r16, g16, b16; r16 = *(r_data++) >> 3; g16 = *(g_data++) >> 2; b16 = *(b_data++) >> 3; *(buffer++) = ((b16 << 11) | (g16 << 5) | r16); }}static const rgbout_packer_t pack_methods[] ={/* name / pixel id / pixel size / scratch / function */ { "ARGB", PX_ARGB, 4, 0, __pack_argb}, {"ARGB1555", PX_ARGB1555, 2, 0, __pack_argb1555}, { "RGB32", PX_RGB32, 4, 0, __pack_rgb32}, { "RGB24", PX_RGB24, 3, 1, __pack_rgb24}, { "RGB16", PX_RGB16, 2, 0, __pack_rgb16}, { "BGRA", PX_BGRA, 4, 0, __pack_bgra}, {"BGRA5551", PX_BGRA5551, 2, 0, __pack_bgra5551}, { "BGR32", PX_BGR32, 4, 0, __pack_bgr32}, { "BGR24", PX_BGR24, 3, 1, __pack_bgr24}, { "BGR26", PX_BGR16, 2, 0, __pack_bgr16}};static uint32_trgbout_get_capabilities(vo_driver_t* vo_driver){ return(VO_CAP_YV12 | VO_CAP_YUY2);}static voidrgbout_frame_field(vo_frame_t* vo_frame, int flags){ /* nothing */}static voidrgbout_frame_dispose(vo_frame_t* vo_frame){ rgbout_frame_t* frame = (rgbout_frame_t*) vo_frame; EVAL(vo_frame != NULL) release(frame->chunk[0]); release(frame->chunk[1]); release(frame->chunk[2]); free(frame);FAILURE: return;}static vo_frame_t*rgbout_alloc_frame(vo_driver_t* vo_driver){ rgbout_driver_t* this = (rgbout_driver_t*) vo_driver; rgbout_frame_t* frame = NULL; EVAL(vo_driver != NULL); EVAL(frame = (rgbout_frame_t*) malloc(sizeof(rgbout_frame_t))); clear(frame, sizeof(rgbout_frame_t)); this->frame = frame; pthread_mutex_init(&(frame->vo_frame.mutex), NULL); frame->vo_frame.proc_slice = NULL; frame->vo_frame.proc_frame = NULL; frame->vo_frame.field = rgbout_frame_field; frame->vo_frame.dispose = rgbout_frame_dispose; frame->vo_frame.driver = vo_driver; if(this->frame_width && this->frame_height) frame->pixels = (this->frame_width * this->frame_height); return((vo_frame_t*) frame);FAILURE: return(NULL);}static voidrgbout_update_frame_format(vo_driver_t* vo_driver, vo_frame_t* vo_frame, uint32_t width, uint32_t height, double ratio, int format, int flags){ rgbout_driver_t* this = (rgbout_driver_t*) vo_driver; rgbout_frame_t* frame = (rgbout_frame_t*) vo_frame; static int told = 0; EVAL(vo_driver != NULL); EVAL(vo_frame != NULL); CHECK(width != 0); CHECK(height != 0); frame->width = width + (width & 1); /* if odd, round to next even number */ frame->height = height + (height & 1); /* if odd, round to next even number */ frame->pixels = frame->width * frame->height; frame->ratio = ratio; frame->format = format; this->lastframe_width = this->frame_width; this->lastframe_height = this->frame_height; this->frame_width = frame->width; this->frame_height = frame->height; release(frame->chunk[0]); release(frame->chunk[1]); release(frame->chunk[2]);CHECK_FRAME: switch(frame->format) { case XINE_IMGFMT_YV12: { if(!(told)) { if (s_debugMessages) fprintf(stderr, THIS ": yuv format is YV12\n"); told = 1; } this->convert = convert_methods[this->cm].convert_yv12; frame->vo_frame.pitches[0] = (frame->width > 7) ? frame->width : 8; frame->vo_frame.pitches[1] = (frame->width > 15) ? (frame->width >> 1) : 8; frame->vo_frame.pitches[2] = frame->vo_frame.pitches[1]; frame->vo_frame.base[0] = (uint8_t*) xine_xmalloc_aligned(16, frame->vo_frame.pitches[0] * frame->height, &(frame->chunk[0])); frame->vo_frame.base[1] = (uint8_t*) xine_xmalloc_aligned(16, frame->vo_frame.pitches[1] * (frame->height >> 1), &(frame->chunk[1])); frame->vo_frame.base[2] = (uint8_t*) xine_xmalloc_aligned(16, frame->vo_frame.pitches[2] * (frame->height >> 1), &(frame->chunk[2])); } break; case XINE_IMGFMT_YUY2: { if(!(told)) { if (s_debugMessages) fprintf(stderr, THIS ": yuv format is YUY2\n"); told = 1; } this->convert = convert_methods[this->cm].convert_yuy2; frame->vo_frame.pitches[0] = (frame->width > 3) ? (frame->width << 1) : 8; frame->vo_frame.pitches[1] = 0; frame->vo_frame.pitches[2] = 0; frame->vo_frame.base[0] = (uint8_t*) xine_xmalloc_aligned(16, frame->vo_frame.pitches[0] * frame->height, &(frame->chunk[0])); frame->vo_frame.base[1] = NULL; frame->vo_frame.base[2] = NULL; } break; default: { if(!(told)) { if (s_debugMessages) fprintf(stderr, THIS ": unknown yuv format [%#x], assuming YV12\n", frame->format); told = 1; } frame->format = XINE_IMGFMT_YV12; goto CHECK_FRAME; } break; } if(this->frame_width != this->lastframe_width || this->frame_height != this->lastframe_height) { release(this->buffer.r); release(this->buffer.g); release(this->buffer.b); release(this->outbuffer); }/* some malloc call can fail; * therefore always check each buffer */ if(!(this->buffer.r)) this->buffer.r = (uint8_t*) xine_xmalloc(frame->pixels + 4); if(!(this->buffer.g)) this->buffer.g = (uint8_t*) xine_xmalloc(frame->pixels + 4); if(!(this->buffer.b)) this->buffer.b = (uint8_t*) xine_xmalloc(frame->pixels + 4); if(!(this->outbuffer)) { uint32_t outbuffer_size = (frame->pixels * pack_methods[this->pm].pixelsize) + pack_methods[this->pm].scratch; EVAL(this->outbuffer = xine_xmalloc(outbuffer_size)); clear(this->outbuffer, outbuffer_size); }FAILURE: return;}/* the only public callback, currently */static intrgbout_update_visual(vo_driver_t* vo_driver, rgbout_visual_info_t* new_visual){ rgbout_driver_t* this = (rgbout_driver_t*) vo_driver; uint32_t i = 0; uint8_t found = 0; uint32_t pm = 0; EVAL(vo_driver != NULL); EVAL(new_visual != NULL); EVAL(new_visual->callback != NULL); for(; i < (sizeof(pack_methods) / sizeof(rgbout_packer_t)); i++) { if(pack_methods[i].id == new_visual->format) { found = 1; pm = i; if(pack_methods[pm].pixelsize != pack_methods[this->pm].pixelsize || pack_methods[pm].scratch > pack_methods[this->pm].scratch) { release(this->outbuffer); } break; } } if(!(found)) { if (s_debugMessages) fprintf(stderr, THIS ": unknown pixel format [%i]\n", new_visual->format); goto FAILURE; } this->pm = pm; this->pack = pack_methods[pm].pack; this->levels = new_visual->levels; this->render = new_visual->callback; return(1);FAILURE: return(0);}static voidrgbout_display_frame(vo_driver_t* vo_driver, vo_frame_t* vo
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -