int txt_render(int size, uint8_t *pdata) { const uint8_t *bp; int left; int lines; int64_t pts; vbi_sliced *psliced = txtdata->sliced; bp = pdata; left = size; if (txtdata) { while ( left > 0 ) { lines = vbi_dvb_demux_cor( txtdata->m_demuxer, psliced, SOFTSUB_SLICED_NB ,&pts, &bp, &left ); if ( lines > 0 ) { vbi_decode( txtdata->m_decoder, psliced, lines, pts/90000.0 ); } } } return 0; }
/***************************************************************************** * Decode: *****************************************************************************/ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; subpicture_t *p_spu = NULL; video_format_t fmt; bool b_cached = false; vbi_page p_page; const uint8_t *p_pos; unsigned int i_left; if( (pp_block == NULL) || (*pp_block == NULL) ) return NULL; p_block = *pp_block; *pp_block = NULL; p_pos = p_block->p_buffer; i_left = p_block->i_buffer; while( i_left > 0 ) { vbi_sliced p_sliced[MAX_SLICES]; unsigned int i_lines = 0; int64_t i_pts; i_lines = vbi_dvb_demux_cor( p_sys->p_dvb_demux, p_sliced, MAX_SLICES, &i_pts, &p_pos, &i_left ); if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, i_pts / 90000.0 ); } /* */ vlc_mutex_lock( &p_sys->lock ); const int i_align = p_sys->i_align; const unsigned int i_wanted_page = p_sys->i_wanted_page; const unsigned int i_wanted_subpage = p_sys->i_wanted_subpage; const bool b_opaque = p_sys->b_opaque; vlc_mutex_unlock( &p_sys->lock ); /* Try to see if the page we want is in the cache yet */ memset( &p_page, 0, sizeof(vbi_page) ); b_cached = vbi_fetch_vt_page( p_sys->p_vbi_dec, &p_page, vbi_dec2bcd( i_wanted_page ), i_wanted_subpage, VBI_WST_LEVEL_3p5, 25, true ); if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update ) goto error; if( !b_cached ) { if( p_sys->i_last_page != i_wanted_page ) { /* We need to reset the subtitle */ p_spu = Subpicture( p_dec, &fmt, true, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; p_spu->p_region->psz_text = strdup(""); p_sys->b_update = true; p_sys->i_last_page = i_wanted_page; goto exit; } goto error; } p_sys->b_update = false; p_sys->i_last_page = i_wanted_page; #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "we now have page: %d ready for display", i_wanted_page ); #endif /* If there is a page or sub to render, then we do that here */ /* Create the subpicture unit */ p_spu = Subpicture( p_dec, &fmt, p_sys->b_text, p_page.columns, p_page.rows, i_align, p_block->i_pts ); if( !p_spu ) goto error; if( p_sys->b_text ) { unsigned int i_textsize = 7000; int i_total; char p_text[i_textsize+1]; i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, 0, p_page.columns, p_page.rows ); p_text[i_total] = '\0'; /* Strip off the pagenumber */ if( i_total <= 40 ) goto error; p_spu->p_region->psz_text = strdup( &p_text[8] ); #ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n%s", p_page.pgno, p_page.subno, i_total, p_text ); #endif } else { picture_t *p_pic = p_spu->p_region->p_picture; /* ZVBI is stupid enough to assume pitch == width */ p_pic->p->i_pitch = 4 * fmt.i_width; vbi_draw_vt_page( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->p_picture->p->p_pixels, 1, 1 ); vlc_mutex_lock( &p_sys->lock ); memcpy( p_sys->nav_link, &p_page.nav_link, sizeof( p_sys->nav_link )) ; vlc_mutex_unlock( &p_sys->lock ); OpaquePage( p_pic, p_page, fmt, b_opaque ); } exit: vbi_unref_page( &p_page ); block_Release( p_block ); return p_spu; error: vbi_unref_page( &p_page ); if( p_spu != NULL ) { decoder_DeleteSubpicture( p_dec, p_spu ); p_spu = NULL; } block_Release( p_block ); return NULL; }
static int dvb_read (vbi_capture * cap, vbi_capture_buffer ** raw, vbi_capture_buffer ** sliced, const struct timeval * timeout) { vbi_capture_dvb *dvb = PARENT (cap, vbi_capture_dvb, capture); vbi_capture_buffer *sb; struct timeval start; struct timeval now; unsigned int n_lines; int64_t pts; if (!sliced || !(sb = *sliced)) { sb = &dvb->sliced_buffer; sb->data = dvb->sliced_data; } start.tv_sec = 0; start.tv_usec = 0; /* When timeout is zero elapsed time doesn't matter. */ if ((timeout->tv_sec | timeout->tv_usec) > 0) gettimeofday (&start, /* timezone */ NULL); now = start; for (;;) { if (0 == dvb->b_left) { ssize_t actual; actual = select_read (dvb, &now, &start, timeout); if (actual <= 0) return actual; gettimeofday (&now, /* timezone */ NULL); /* XXX inaccurate. Should be the time when we received the first byte of the first packet containing data of the returned frame. Or so. */ dvb->sample_time = now.tv_sec + now.tv_usec * (1 / 1e6); dvb->bp = dvb->pes_buffer; dvb->b_left = actual; } /* Demultiplexer coroutine. Returns when one frame is complete or the buffer is empty, advancing bp and b_left. Don't change sb->data in flight. */ /* XXX max sliced lines needs an API change. Currently this value is determined by vbi_raw_decoder line count below, 256 / 2 because fields don't really apply here and in practice even 32 should be enough. */ n_lines = vbi_dvb_demux_cor (dvb->demux, sb->data, /* max sliced lines */ 128, &pts, &dvb->bp, &dvb->b_left); if (n_lines > 0) break; if (dvb->bug_compatible) { /* Only one read(), timeout ignored. */ return 0; /* timeout */ } else { /* Read until EAGAIN, another error or the timeout expires, in this order. */ } } if (sliced) { sb->size = n_lines * sizeof (vbi_sliced); sb->timestamp = dvb->sample_time; /* XXX PTS needs an API change. sb->sample_time = dvb->sample_time; sb->stream_time = pts; (first sliced line) */ dvb->last_pts = pts; *sliced = sb; } if (raw && *raw) { /* Not implemented yet. */ sb = *raw; sb->size = 0; } return 1; /* success */ }