rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl) { rtsp_session_t *rtsp_session = calloc(1, sizeof(rtsp_session_t)); xine_t *xine = stream->xine; char *server; char *mrl_line=strdup(mrl); rmff_header_t *h; int bandwidth_id; uint32_t bandwidth; bandwidth_id = xine->config->register_enum(xine->config, "media.network.bandwidth", 10, rtsp_bandwidth_strs, _("network bandwidth"), _("Specify the bandwidth of your internet connection here. " "This will be used when streaming servers offer different versions " "with different bandwidth requirements of the same stream."), 0, NULL, NULL); bandwidth = rtsp_bandwidths[bandwidth_id]; rtsp_session->recv = xine_buffer_init(BUF_SIZE); connect: /* connect to server */ rtsp_session->s=rtsp_connect(stream, mrl_line, NULL); if (!rtsp_session->s) { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: failed to connect to server %s\n"), mrl_line); xine_buffer_free(rtsp_session->recv); free(rtsp_session); return NULL; } /* looking for server type */ if (rtsp_search_answers(rtsp_session->s,"Server")) server=strdup(rtsp_search_answers(rtsp_session->s,"Server")); else { if (rtsp_search_answers(rtsp_session->s,"RealChallenge1")) server=strdup("Real"); else server=strdup("unknown"); } if (strstr(server,"Real") || strstr(server,"Helix")) { /* we are talking to a real server ... */ h=real_setup_and_get_header(rtsp_session->s, bandwidth); if (!h) { /* got an redirect? */ if (rtsp_search_answers(rtsp_session->s, "Location")) { free(mrl_line); mrl_line=strdup(rtsp_search_answers(rtsp_session->s, "Location")); xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "rtsp_session: redirected to %s\n", mrl_line); rtsp_close(rtsp_session->s); free(server); goto connect; /* *shudder* i made a design mistake somewhere */ } else { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: session can not be established.\n")); rtsp_close(rtsp_session->s); xine_buffer_free(rtsp_session->recv); free(rtsp_session); return NULL; } } rtsp_session->header_left = rtsp_session->header_len = rmff_dump_header(h,rtsp_session->header,HEADER_SIZE); if (rtsp_session->header_len < 0) { xprintf (stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: rtsp server returned overly-large headers, session can not be established.\n")); goto session_abort; } xine_buffer_copyin(rtsp_session->recv, 0, rtsp_session->header, rtsp_session->header_len); rtsp_session->recv_size = rtsp_session->header_len; rtsp_session->recv_read = 0; } else { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: rtsp server type '%s' not supported yet. sorry.\n"), server); session_abort: rtsp_close(rtsp_session->s); free(server); xine_buffer_free(rtsp_session->recv); free(rtsp_session); return NULL; } free(server); return rtsp_session; }
static void jpeg_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { jpeg_decoder_t *this = (jpeg_decoder_t *) this_gen; if (!this->video_open) { lprintf("opening video\n"); (this->stream->video_out->open) (this->stream->video_out, this->stream); this->video_open = 1; } xine_buffer_copyin(this->image, this->index, buf->mem, buf->size); this->index += buf->size; if (buf->decoder_flags & BUF_FLAG_FRAME_END && this->index > 0) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPARRAY buffer; int i, linesize; int width, height; vo_frame_t *img; int max_width, max_height; uint8_t *slice_start[1] = {NULL}; int slice_line = 0; /* query max. image size vo can handle */ max_width = this->stream->video_out->get_property( this->stream->video_out, VO_PROP_MAX_VIDEO_WIDTH); max_height = this->stream->video_out->get_property( this->stream->video_out, VO_PROP_MAX_VIDEO_HEIGHT); /* init and parse header */ cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); jpeg_memory_src(&cinfo, this->image, this->index); jpeg_read_header(&cinfo, TRUE); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, cinfo.image_width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, cinfo.image_height); lprintf("header parsed\n"); /* set decoding parameters */ cinfo.out_color_space = JCS_YCbCr; /* request scaling when image is too large for vo */ if (this->cls->enable_downscaling) { cinfo.output_width = cinfo.image_width; cinfo.output_height = cinfo.image_height; cinfo.scale_num = 1; cinfo.scale_denom = 1; while ((max_width > 0 && cinfo.output_width > max_width) || (max_height > 0 && cinfo.output_height > max_height)) { cinfo.scale_denom <<= 1; cinfo.output_width >>= 1; cinfo.output_height >>= 1; } if (cinfo.scale_denom > 1) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": downscaling image by 1:%d to %dx%d\n", cinfo.scale_denom, cinfo.output_width, cinfo.output_height); } } /* start decompress */ jpeg_start_decompress(&cinfo); width = cinfo.output_width; height = cinfo.output_height; /* crop when image is too large for vo */ if (max_width > 0 && cinfo.output_width > max_width) width = max_width; if (max_height > 0 && cinfo.output_height > max_height) height = max_height; img = this->stream->video_out->get_frame (this->stream->video_out, width, height, (double)width/(double)height, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); linesize = cinfo.output_width * cinfo.output_components; buffer = (cinfo.mem->alloc_sarray)((void*)&cinfo, JPOOL_IMAGE, linesize, 1); if (img->proc_slice && !(img->height & 0xf)) { slice_start[0] = img->base[0]; } /* cut to frame width */ if (cinfo.output_width > img->width) { lprintf("cut right border %d pixels\n", cinfo.output_width - img->width); linesize = img->width * 3; } /* YUV444->YUV422 simple */ while (cinfo.output_scanline < cinfo.output_height) { uint8_t *dst = img->base[0] + img->pitches[0] * cinfo.output_scanline; jpeg_read_scanlines(&cinfo, buffer, 1); /* cut to frame height */ if (cinfo.output_scanline > img->height) { lprintf("cut bottom scanline %d\n", cinfo.output_scanline - 1); continue; } for (i = 0; i < linesize; i += 3) { *dst++ = buffer[0][i]; if (i & 1) { *dst++ = buffer[0][i + 2]; } else { *dst++ = buffer[0][i + 1]; } } if (slice_start[0]) { slice_line++; if (slice_line == 16) { img->proc_slice(img, slice_start); slice_start[0] += 16 * img->pitches[0]; slice_line = 0; } } } /* final slice */ if (slice_start[0] && slice_line) { img->proc_slice(img, slice_start); } jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); img->pts = buf->pts; img->duration = 3600; img->bad_frame = 0; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, img->duration); img->draw(img, this->stream); img->free(img); this->index = 0; }