G_GNUC_INTERNAL void stream_h264_data(display_stream *st) { int width, height; uint8_t *data; int size = stream_get_current_frame(st, &data); stream_get_dimensions(st, &width, &height); if(st->stream_width != width || st->stream_height != height) { st->stream_width = width; st->stream_height = height; stream_h264_finit(st); stream_h264_init(st); st->rgba_buf = g_malloc0(st->stream_width * st->stream_height * 4); } st->out_frame = st->rgba_buf; av_init_packet(&st->packet); st->packet.data = data; st->packet.size = size; decode_packet(st, width, height); av_free_packet(&st->packet); }
G_GNUC_INTERNAL void stream_mjpeg_data(display_stream *st) { gboolean back_compat = st->channel->priv->peer_hdr.major_version == 1; int width; int height; uint8_t *dest; uint8_t *lines[4]; stream_get_dimensions(st, &width, &height); dest = malloc(width * height * 4); if (st->out_frame) { free(st->out_frame); } st->out_frame = dest; jpeg_read_header(&st->mjpeg_cinfo, 1); #ifdef JCS_EXTENSIONS // requires jpeg-turbo if (back_compat) st->mjpeg_cinfo.out_color_space = JCS_EXT_RGBX; else st->mjpeg_cinfo.out_color_space = JCS_EXT_BGRX; #else #warning "You should consider building with libjpeg-turbo" st->mjpeg_cinfo.out_color_space = JCS_RGB; #endif #ifndef SPICE_QUALITY st->mjpeg_cinfo.dct_method = JDCT_IFAST; st->mjpeg_cinfo.do_fancy_upsampling = FALSE; st->mjpeg_cinfo.do_block_smoothing = FALSE; st->mjpeg_cinfo.dither_mode = JDITHER_ORDERED; #endif // TODO: in theory should check cinfo.output_height match with our height jpeg_start_decompress(&st->mjpeg_cinfo); /* rec_outbuf_height is the recommended size of the output buffer we * pass to libjpeg for optimum performance */ if (st->mjpeg_cinfo.rec_outbuf_height > G_N_ELEMENTS(lines)) { jpeg_abort_decompress(&st->mjpeg_cinfo); g_return_if_reached(); } while (st->mjpeg_cinfo.output_scanline < st->mjpeg_cinfo.output_height) { /* only used when JCS_EXTENSIONS is undefined */ G_GNUC_UNUSED unsigned int lines_read; for (unsigned int j = 0; j < st->mjpeg_cinfo.rec_outbuf_height; j++) { lines[j] = dest; #ifdef JCS_EXTENSIONS dest += 4 * width; #else dest += 3 * width; #endif } lines_read = jpeg_read_scanlines(&st->mjpeg_cinfo, lines, st->mjpeg_cinfo.rec_outbuf_height); #ifndef JCS_EXTENSIONS { uint8_t *s = lines[0]; uint32_t *d = (uint32_t *)s; if (back_compat) { for (unsigned int j = lines_read * width; j > 0; ) { j -= 1; // reverse order, bad for cache? d[j] = s[j * 3 + 0] | s[j * 3 + 1] << 8 | s[j * 3 + 2] << 16; } } else { for (unsigned int j = lines_read * width; j > 0; ) { j -= 1; // reverse order, bad for cache? d[j] = s[j * 3 + 0] << 16 | s[j * 3 + 1] << 8 | s[j * 3 + 2]; } } } #endif dest = &st->out_frame[st->mjpeg_cinfo.output_scanline * width * 4]; } jpeg_finish_decompress(&st->mjpeg_cinfo); }