int framecatcher::getRGBImage(int frame, unsigned char*& rgb32BitData, int& width, int& height){ if(stream == NULL) return 0; int errCode = 0; xine_play(stream,0,0); xine_play(stream,0,frame); // 1 frame 2 mseconds uint8_t *yuv = NULL, *y = NULL, *u = NULL, *v =NULL ; int ratio = 0, format = 0; if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, NULL)){ errCode= xine_get_error(stream); return errCode; } yuv = new uint8_t[((width+8) * (height+1) * 2)]; if (yuv == NULL){ std::cerr << "Out of Memory!"; return 0; } if (!xine_get_current_frame(stream, &width, &height, &ratio, &format, yuv)){ errCode= xine_get_error(stream); if(yuv != NULL) delete[] yuv; return errCode; } /* * convert to yv12 if necessary */ switch (format){ case XINE_IMGFMT_YUY2: { uint8_t *yuy2 = yuv; yuv = new uint8_t[(width * height * 2)]; if (yuv == NULL){ std::cerr << "Not enough memory to make screenshot!" << std::endl; return 0; } y = yuv; u = yuv + width * height; v = yuv + width * height * 5 / 4; yuy2Toyv12 (y, u, v, yuy2, width, height); delete [] yuy2; } break; case XINE_IMGFMT_YV12: y = yuv; u = yuv + width * height; v = yuv + width * height * 5 / 4; break; default: { std::cerr << "Format Not Supported" << std::endl; if(yuv != NULL) delete [] yuv; return 0; } } rgb32BitData = yv12ToRgb (y, u, v, width, height); delete [] yuv; return 1; }
static Epsilon_Image * epsilon_generate_thumb (Epsilon * e) { int ret = XINE_THUMB_SUCCESS; Epsilon_Image *img = NULL; unsigned char *buf = NULL; int cnt, attempts = 0, length = -1, pos_perc, pos_time, new_perc, new_time, req_perc = 500, req_time = 500; static int old_length = -1; char cfg[PATH_MAX]; epsilon_xine_param *param; param = calloc (1, sizeof (epsilon_xine_param)); if (!(param->xine = xine_new ())) { return NULL; } snprintf (cfg, PATH_MAX, "%s%s", xine_get_homedir (), ".xine/config"); xine_config_load (param->xine, cfg); xine_init (param->xine); /* opening xine output ports */ if (! (param->vo_port = xine_open_video_driver (param->xine, "none", XINE_VISUAL_TYPE_NONE, (void *) NULL))) { goto done; } param->ao_port = xine_open_audio_driver (param->xine, "none", NULL); /* open a xine stream connected to these ports */ if (! (param->stream = xine_stream_new (param->xine, param->ao_port, param->vo_port))) { goto done; } if (!xine_open (param->stream, e->src)) { ret = XINE_THUMB_FAIL; goto done; } if (XINE_THUMBNAILER_DEBUG) printf("Starting xine thumbnail process..\n"); try_get_chance: new_perc = -1; new_time = req_time; if (!xine_play (param->stream, 0, new_time)) { new_time = -1; new_perc = req_perc; /* 0..65535 */ if (!xine_play (param->stream, new_perc, 0)) { ret = XINE_THUMB_FAIL; if (XINE_THUMBNAILER_DEBUG) printf("Coudln't play video %s..\n", e->src); goto close_stream; } } /* get position */ for (cnt = 0; ((cnt < 50) && (!xine_get_pos_length (param->stream, &pos_perc, &pos_time, &length) || (length == old_length))); cnt++) usleep (1000); if (length < 0) { if (XINE_THUMBNAILER_DEBUG) printf("Video is 0 length!..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } /* wait till position changes */ for (cnt = 0; (cnt < 50) && (!xine_get_pos_length (param->stream, &new_perc, &new_time, &length) || ((new_perc == pos_perc) && (new_time == pos_time))); cnt++) { usleep (1000); } /* get snapshot */ int w, h, ratio, format; old_length = length; /* ask what size a snapshot would be (if we can make one) */ if (!xine_get_current_frame (param->stream, &w, &h, &ratio, &format, NULL)) { attempts++; if (attempts < 10) { if (req_time < 10000) req_time += 1000; if (req_perc < 10000) req_perc += 1000; goto try_get_chance; } else { if (XINE_THUMBNAILER_DEBUG) printf("Exhausted attempts to thumbnail..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } } else if ((w <= 0) || (h <= 0)) { if (XINE_THUMBNAILER_DEBUG) printf("Width/Height of video invalid: %d:%d..\n", w,h); ret = XINE_THUMB_FAIL; goto close_stream; } else { /* know we know the size, get a buffer for the snapshot */ if (!(buf = malloc (w * h * 2))) { if (XINE_THUMBNAILER_DEBUG) printf("Couldn't allocate memory for thumbnail buffer..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } /* make a snapshot! */ if (!xine_get_current_frame (param->stream, &w, &h, &ratio, &format, buf)) { if (XINE_THUMBNAILER_DEBUG) printf("Couldn't retrieve current video frame..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } else if ((w <= 0) || (h <= 0)) { if (XINE_THUMBNAILER_DEBUG) printf("Width/height of video invalid: %d:%d..\n",w,h); ret = XINE_THUMB_FAIL; goto close_stream; } if (format == XINE_IMGFMT_YUY2) { unsigned char *buf2 = malloc (w * h * 2); unsigned char *tmp = buf; i_yuy2_to_yv12 (buf, buf2, w, h); buf = buf2; free (tmp); format = XINE_IMGFMT_YV12; } if (format == XINE_IMGFMT_YV12) { ret = yv12_to_rgb (e->src, w, h, &buf, &img); if (ret != XINE_THUMB_SUCCESS) { if (img) { if (++attempts > 10) goto close_stream; free(img->data); free(img); img = NULL; if (ret == XINE_THUMB_RETRY) { if (buf) { free (buf); buf = NULL; if ((req_perc += (attempts * 1000)) > 65535) req_perc = 1000; if ((req_time += (attempts * 2500)) > length) req_time = 3000; goto try_get_chance; } if (XINE_THUMBNAILER_DEBUG) printf("Exhausted attempts to thumbnail pos 2..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } } else { if (XINE_THUMBNAILER_DEBUG) printf("Couldn't complete yv12_to_rgb..\n"); ret = XINE_THUMB_FAIL; goto close_stream; } } } ret = XINE_THUMB_SUCCESS; close_stream: if (buf) { free (buf); buf = NULL; } xine_close (param->stream); done: if (ret != XINE_THUMB_SUCCESS) { if (img) { free(img->data); free(img); img = NULL; } } if (param->stream) { xine_dispose (param->stream); param->stream = NULL; } if (param->ao_port) { xine_close_audio_driver (param->xine, param->ao_port); param->ao_port = NULL; } if (param->vo_port) { xine_close_video_driver (param->xine, param->vo_port); param->vo_port = NULL; } free (param); return img; } return NULL; }