/***************************************************************************** * 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; if( (pp_block == NULL) || (*pp_block == NULL) ) return NULL; p_block = *pp_block; *pp_block = NULL; if( p_block->i_buffer > 0 && ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) || ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) ) { vbi_sliced *p_sliced = p_sys->p_vbi_sliced; unsigned int i_lines = 0; p_block->i_buffer--; p_block->p_buffer++; while( p_block->i_buffer >= 2 ) { int i_id = p_block->p_buffer[0]; unsigned i_size = p_block->p_buffer[1]; if( 2 + i_size > p_block->i_buffer ) break; if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES ) { if(p_block->p_buffer[3] == 0xE4 ) /* framing_code */ { unsigned line_offset = p_block->p_buffer[2] & 0x1f; unsigned field_parity = p_block->p_buffer[2] & 0x20; p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B; if( line_offset > 0 ) p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313); else p_sliced[i_lines].line = 0; for( int i = 0; i < 42; i++ ) p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] ); i_lines++; } } p_block->i_buffer -= 2 + i_size; p_block->p_buffer += 2 + i_size; } if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, 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->b_text && 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; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->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 /* Ignore transparent rows at the beginning and end */ int i_first_row = get_first_visible_row( p_page.text, p_page.rows, p_page.columns ); int i_num_rows; if ( i_first_row < 0 ) { i_first_row = p_page.rows - 1; i_num_rows = 0; } else { i_num_rows = get_last_visible_row( p_page.text, p_page.rows, p_page.columns ) - i_first_row + 1; } #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "After top and tail of page we have rows %i-%i of %i", i_first_row + 1, i_first_row + i_num_rows, p_page.rows ); #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, i_num_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,offset; // char p_text[i_textsize+1]; char *p_text = (char *)malloc(i_textsize+1); // sunqueen modify i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, i_first_row, p_page.columns, i_num_rows ); for( offset=1; offset<i_total && isspace( p_text[i_total-offset ] ); offset++) p_text[i_total-offset] = '\0'; i_total -= offset; offset=0; while( offset < i_total && isspace( p_text[offset] ) ) offset++; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->text = strdup( &p_text[offset] ); p_spu_sys->align = i_align; p_spu_sys->i_font_height_percent = 5; p_spu_sys->renderbg = b_opaque; #ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n\"%s\"", p_page.pgno, p_page.subno, i_total, &p_text[offset] ); #endif free(p_text); // sunqueen add } 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; /* Maintain subtitle postion */ p_spu->p_region->i_y = i_first_row*10; p_spu->i_original_picture_width = p_page.columns*12; p_spu->i_original_picture_height = p_page.rows*10; vbi_draw_vt_page_region( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->p_picture->p->p_pixels, -1, 0, i_first_row, p_page.columns, i_num_rows, 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, i_first_row * p_page.columns ); } 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; }
/***************************************************************************** * 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; }
void VBIDecoder::eventHandler(vbi_event* event) { vbi_page page; switch (event->type) { case VBI_EVENT_CLOSE: fprintf(fplog, "vbi_event: type=CLOSE\n"); break; case VBI_EVENT_TTX_PAGE: // UNTESTED! fprintf(fplog, "vbi_event: type=TTX_PAGE pgno=%d subno=%d\n", event->ev.ttx_page.pgno, event->ev.ttx_page.subno); if (event->ev.ttx_page.pgno != pageno) { break; } if (!vbi_fetch_vt_page(decoder, &page, event->ev.ttx_page.pgno, event->ev.ttx_page.subno, VBI_WST_LEVEL_3p5, 25, TRUE)) break; if (checkPageSize) setTeletext(&page); checkPage(&page); vbi_unref_page(&page); break; case VBI_EVENT_CAPTION: if (event->ev.caption.pgno != pageno) { if (verbose) fprintf(fplog, "vbi_event: type=CAPTION pgno=%d curr=%.4f ignored\n", event->ev.caption.pgno, (double)currTimestamp); break; } if (!vbi_fetch_cc_page(decoder, &page, event->ev.caption.pgno, TRUE)) break; if (verbose) { fprintf(fplog, "vbi_event: type=CAPTION pgno=%d curr=%.4f dirty: y=%d,%d roll=%d\n", event->ev.caption.pgno, (double)currTimestamp, page.dirty.y0, page.dirty.y1, page.dirty.roll); fflush(fplog); } if (checkPageSize) setCaption(&page); checkPage(&page); vbi_unref_page(&page); break; case VBI_EVENT_NETWORK: fprintf(fplog, "vbi_event: type=NETWORK\n"); break; case VBI_EVENT_TRIGGER: fprintf(fplog, "vbi_event: type=TRIGGER\n"); break; case VBI_EVENT_ASPECT: fprintf(fplog, "vbi_event: type=ASPECT\n"); break; case VBI_EVENT_PROG_INFO: fprintf(fplog, "vbi_event: type=PROG_INFO\n"); break; case VBI_EVENT_NETWORK_ID: fprintf(fplog, "vbi_event: type=NETWORK_ID\n"); break; default: fprintf(fplog, "vbi_event: type=%#x\n", event->type); break; } }
/***************************************************************************** * Decode: *****************************************************************************/ static int Decode( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; subpicture_t *p_spu = NULL; video_format_t fmt; bool b_cached = false; vbi_page p_page; if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; if( p_block->i_buffer > 0 && ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) || ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) ) { vbi_sliced *p_sliced = p_sys->p_vbi_sliced; unsigned int i_lines = 0; p_block->i_buffer--; p_block->p_buffer++; while( p_block->i_buffer >= 2 ) { int i_id = p_block->p_buffer[0]; unsigned i_size = p_block->p_buffer[1]; if( 2 + i_size > p_block->i_buffer ) break; if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES ) { if(p_block->p_buffer[3] == 0xE4 ) /* framing_code */ { unsigned line_offset = p_block->p_buffer[2] & 0x1f; unsigned field_parity = p_block->p_buffer[2] & 0x20; p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B; if( line_offset > 0 ) p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313); else p_sliced[i_lines].line = 0; for( int i = 0; i < 42; i++ ) p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] ); i_lines++; } } p_block->i_buffer -= 2 + i_size; p_block->p_buffer += 2 + i_size; } if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, 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; const unsigned int i_level = p_sys->i_level > 3 ? 3 : p_sys->i_level; 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, level_zvbi_values[i_level], 25, true ); if( i_wanted_page == p_sys->i_last_page && !p_sys->b_update ) goto error; if( !b_cached ) { if( p_sys->b_text && 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; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->region.p_segments = text_segment_New(""); 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 /* Ignore transparent rows at the beginning and end */ int i_first_row = get_first_visible_row( p_page.text, p_page.rows, p_page.columns ); int i_num_rows; if ( i_first_row < 0 ) { i_first_row = p_page.rows - 1; i_num_rows = 0; } else { i_num_rows = get_last_visible_row( p_page.text, p_page.rows, p_page.columns ) - i_first_row + 1; } #ifdef ZVBI_DEBUG msg_Dbg( p_dec, "After top and tail of page we have rows %i-%i of %i", i_first_row + 1, i_first_row + i_num_rows, p_page.rows ); #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, i_num_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,offset; char p_text[i_textsize+1]; i_total = vbi_print_page_region( &p_page, p_text, i_textsize, "UTF-8", 0, 0, 0, i_first_row, p_page.columns, i_num_rows ); for( offset=1; offset<i_total && isspace( p_text[i_total-offset ] ); offset++) p_text[i_total-offset] = '\0'; i_total -= offset; offset=0; while( offset < i_total && isspace( p_text[offset] ) ) offset++; subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; p_spu_sys->region.p_segments = text_segment_New( &p_text[offset] ); if( p_spu_sys->region.p_segments && b_opaque ) { p_spu_sys->region.p_segments->style = text_style_Create( STYLE_NO_DEFAULTS ); if( p_spu_sys->region.p_segments->style ) { /* Set text background */ p_spu_sys->region.p_segments->style->i_style_flags = STYLE_BACKGROUND; p_spu_sys->region.p_segments->style->i_features |= STYLE_HAS_FLAGS; } } p_spu_sys->region.inner_align = i_align; p_spu_sys->region.flags = UPDT_REGION_IGNORE_BACKGROUND; #ifdef ZVBI_DEBUG msg_Info( p_dec, "page %x-%x(%d)\n\"%s\"", p_page.pgno, p_page.subno, i_total, &p_text[offset] ); #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; /* Maintain subtitle postion */ p_spu->p_region->i_y = i_first_row*10; p_spu->i_original_picture_width = p_page.columns*12; p_spu->i_original_picture_height = p_page.rows*10; vbi_draw_vt_page_region( &p_page, ZVBI_PIXFMT_RGBA32, p_spu->p_region->p_picture->p->p_pixels, -1, 0, i_first_row, p_page.columns, i_num_rows, 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, i_first_row * p_page.columns ); } exit: vbi_unref_page( &p_page ); block_Release( p_block ); if( p_spu ) decoder_QueueSub( p_dec, p_spu ); return VLCDEC_SUCCESS; error: vbi_unref_page( &p_page ); block_Release( p_block ); return VLCDEC_SUCCESS; }
static GstFlowReturn gst_teletextdec_push_page (GstTeletextDec * teletext) { GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf; vbi_page page; page_info *pi; gint pgno, subno; gboolean success; pi = (page_info *) g_queue_pop_head (teletext->queue); pgno = vbi_bcd2dec (pi->pgno); subno = vbi_bcd2dec (pi->subno); GST_INFO_OBJECT (teletext, "Fetching teletext page %03d.%02d", pgno, subno); success = vbi_fetch_vt_page (teletext->decoder, &page, pi->pgno, pi->subno, VBI_WST_LEVEL_3p5, 25, FALSE); if (G_UNLIKELY (!success)) goto fetch_page_failed; switch (teletext->output_format) { case GST_TELETEXTDEC_OUTPUT_FORMAT_TEXT: ret = gst_teletextdec_export_text_page (teletext, &page, &buf); break; case GST_TELETEXTDEC_OUTPUT_FORMAT_HTML: ret = gst_teletextdec_export_html_page (teletext, &page, &buf); break; case GST_TELETEXTDEC_OUTPUT_FORMAT_RGBA: ret = gst_teletextdec_export_rgba_page (teletext, &page, &buf); break; case GST_TELETEXTDEC_OUTPUT_FORMAT_PANGO: ret = gst_teletextdec_export_pango_page (teletext, &page, &buf); break; default: g_assert_not_reached (); break; } vbi_unref_page (&page); g_free (pi); if (ret != GST_FLOW_OK) goto alloc_failed; GST_BUFFER_TIMESTAMP (buf) = teletext->in_timestamp; GST_BUFFER_DURATION (buf) = teletext->in_duration; GST_INFO_OBJECT (teletext, "Pushing buffer of size %d", GST_BUFFER_SIZE (buf)); ret = gst_pad_push (teletext->srcpad, buf); if (ret != GST_FLOW_OK) goto push_failed; return GST_FLOW_OK; fetch_page_failed: { GST_ELEMENT_ERROR (teletext, RESOURCE, READ, (NULL), (NULL)); return GST_FLOW_ERROR; } alloc_failed: { GST_ERROR_OBJECT (teletext, "Error allocating output buffer, reason %s", gst_flow_get_name (ret)); return ret; } push_failed: { GST_ERROR_OBJECT (teletext, "Pushing buffer failed, reason %s", gst_flow_get_name (ret)); return ret; } }
static void do_export (vbi_pgno pgno, vbi_subno subno) { vbi_page page; vbi_bool success; if (option_delay > 1) { --option_delay; return; } success = vbi_fetch_vt_page (vbi, &page, pgno, subno, VBI_WST_LEVEL_3p5, /* n_rows */ 25, /* navigation */ TRUE); if (!success) { /* Shouldn't happen. */ error_exit (_("Unknown error.")); } if (option_dump_pg) { page_dump (&page); } switch (option_target) { char *file_name; void *buffer; void *buffer2; FILE *fp; size_t size; ssize_t ssize; case 1: buffer = malloc (1 << 20); if (NULL == buffer) no_mem_exit (); ssize = vbi_export_mem (ex, buffer, 1 << 20, &page); success = (ssize >= 0); if (success) { ssize_t ssize2; fp = open_output_file (pgno, subno); if (1 != fwrite (buffer, ssize, 1, fp)) write_error_exit (/* msg: errno */ NULL); close_output_file (fp); /* Test. */ ssize2 = vbi_export_mem (ex, buffer, 0, &page); assert (ssize == ssize2); assert (ssize > 0); ssize2 = vbi_export_mem (ex, buffer, ssize - 1, &page); assert (ssize == ssize2); } free (buffer); break; case 2: buffer = NULL; buffer2 = vbi_export_alloc (ex, &buffer, &size, &page); /* Test. */ assert (buffer == buffer2); success = (NULL != buffer); if (success) { fp = open_output_file (pgno, subno); if (1 != fwrite (buffer, size, 1, fp)) write_error_exit (/* msg: errno */ NULL); close_output_file (fp); free (buffer); } break; case 3: /* This is the default target. The other cases are only implemented for tests and will be removed when I wrote proper unit tests. */ fp = open_output_file (pgno, subno); success = vbi_export_stdio (ex, fp, &page); close_output_file (fp); break; case 5: file_name = output_file_name (pgno, subno); success = vbi_export_file (ex, file_name, &page); free (file_name); break; default: error_exit ("Invalid target %u.", option_target); break; } if (!success) { error_exit (_("Export of page %x failed: %s"), pgno, vbi_export_errstr (ex)); } vbi_unref_page (&page); }
/***************************************************************************** * 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; if( (pp_block == NULL) || (*pp_block == NULL) ) return NULL; p_block = *pp_block; *pp_block = NULL; if( p_block->i_buffer > 0 && ( ( p_block->p_buffer[0] >= 0x10 && p_block->p_buffer[0] <= 0x1f ) || ( p_block->p_buffer[0] >= 0x99 && p_block->p_buffer[0] <= 0x9b ) ) ) { vbi_sliced *p_sliced = p_sys->p_vbi_sliced; unsigned int i_lines = 0; p_block->i_buffer--; p_block->p_buffer++; while( p_block->i_buffer >= 2 ) { int i_id = p_block->p_buffer[0]; unsigned i_size = p_block->p_buffer[1]; if( 2 + i_size > p_block->i_buffer ) break; if( ( i_id == 0x02 || i_id == 0x03 ) && i_size >= 44 && i_lines < MAX_SLICES ) { unsigned line_offset = p_block->p_buffer[2] & 0x1f; unsigned field_parity = p_block->p_buffer[2] & 0x20; p_sliced[i_lines].id = VBI_SLICED_TELETEXT_B; if( line_offset > 0 ) p_sliced[i_lines].line = line_offset + (field_parity ? 0 : 313); else p_sliced[i_lines].line = 0; for( int i = 0; i < 42; i++ ) p_sliced[i_lines].data[i] = vbi_rev8( p_block->p_buffer[4 + i] ); i_lines++; } p_block->i_buffer -= 2 + i_size; p_block->p_buffer += 2 + i_size; } if( i_lines > 0 ) vbi_decode( p_sys->p_vbi_dec, p_sliced, i_lines, (double)p_block->i_pts / 1000000 ); } /* */ 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; }