Esempio n. 1
0
static void
mainloop			(void)
{
	struct timeval timeout;
	vbi_capture_buffer *sliced_buffer;
	unsigned int n_frames;

	/* Don't wait more than two seconds for the driver
	   to return data. */
	timeout.tv_sec = 2;
	timeout.tv_usec = 0;

	/* Should receive a CNI within two seconds,
	   call sign within ten seconds(?). */
	if (services & VBI_SLICED_CAPTION_525)
		n_frames = 11 * 30;
	else
		n_frames = 3 * 25;

	for (; n_frames > 0; --n_frames) {
		unsigned int n_lines;
		int r;

		r = vbi_capture_pull (cap,
				      /* raw_buffer */ NULL,
				      &sliced_buffer,
				      &timeout);
		switch (r) {
		case -1:
			fprintf (stderr, "VBI read error %d (%s)\n",
				 errno, strerror (errno));
			/* Could be ignored, esp. EIO with some drivers. */
			exit (EXIT_FAILURE);

		case 0: 
			fprintf (stderr, "VBI read timeout\n");
			exit (EXIT_FAILURE);

		case 1: /* success */
			break;

		default:
			assert (0);
		}

		n_lines = sliced_buffer->size / sizeof (vbi_sliced);

		vbi_decode (dec,
			    (vbi_sliced *) sliced_buffer->data,
			    n_lines,
			    sliced_buffer->timestamp);

		if (quit)
			return;
	}

	printf ("No network ID received or network unknown.\n");
}
Esempio n. 2
0
static void
gst_teletextdec_process_telx_buffer (GstTeletextDec * teletext, GstBuffer * buf)
{
  guint8 *data = GST_BUFFER_DATA (buf);
  const gint size = GST_BUFFER_SIZE (buf);
  guint offset = 0;
  gint res;

  teletext->in_timestamp = GST_BUFFER_TIMESTAMP (buf);
  teletext->in_duration = GST_BUFFER_DURATION (buf);

  if (teletext->frame == NULL) {
    gst_teletextdec_reset_frame (teletext);
  }

  while (offset < size) {
    res =
        gst_teletextdec_extract_data_units (teletext, teletext->frame, data,
        &offset, size);

    if (res == VBI_NEW_FRAME) {
      /* We have a new frame, it's time to feed the decoder */
      vbi_sliced *s;
      gint n_lines;

      n_lines = teletext->frame->current_slice - teletext->frame->sliced_begin;
      GST_LOG_OBJECT (teletext, "Completed frame, decoding new %d lines",
          n_lines);
      s = g_memdup (teletext->frame->sliced_begin,
          n_lines * sizeof (vbi_sliced));
      vbi_decode (teletext->decoder, s, n_lines, teletext->last_ts);
      /* From vbi_decode():
       * timestamp shall advance by 1/30 to 1/25 seconds whenever calling this
       * function. Failure to do so will be interpreted as frame dropping, which
       * starts a resynchronization cycle, eventually a channel switch may be assumed
       * which resets even more decoder state. So even if a frame did not contain
       * any useful data this function must be called, with lines set to zero.
       */
      teletext->last_ts += 0.04;

      g_free (s);
      gst_teletextdec_reset_frame (teletext);
    } else if (res == VBI_ERROR) {
      gst_teletextdec_reset_frame (teletext);
      return;
    }
  }
  return;
}
Esempio n. 3
0
static void
cmd				(unsigned int		n)
{
	vbi_sliced sliced;
	static double time = 0.0;

	sliced.id = VBI_SLICED_CAPTION_525;
	sliced.line = 21;
	sliced.data[0] = vbi_par8 (n >> 8);
	sliced.data[1] = vbi_par8 (n & 0x7F);

	vbi_decode (vbi, &sliced, 1, time);

	xevent (33333);

	time += 1 / 29.97;
}
Esempio n. 4
0
static void
mainloop			(void)
{
    struct timeval timeout;

    /* Don't wait more than two seconds for the driver
       to return data. */
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;

    for (;;) {
        vbi_capture_buffer *sliced_buffer;
        unsigned int n_lines;
        int r;

        r = vbi_capture_pull (cap,
                              /* raw_buffer */ NULL,
                              &sliced_buffer,
                              &timeout);
        switch (r) {
        case -1:
            fprintf (stderr, "VBI read error %d (%s)\n",
                     errno, strerror (errno));
            /* Could be ignored, esp. EIO with some drivers. */
            exit (EXIT_FAILURE);

        case 0:
            fprintf (stderr, "VBI read timeout\n");
            exit (EXIT_FAILURE);

        case 1: /* success */
            break;

        default:
            assert (0);
        }

        n_lines = sliced_buffer->size / sizeof (vbi_sliced);

        vbi_decode (dec,
                    (vbi_sliced *) sliced_buffer->data,
                    n_lines,
                    sliced_buffer->timestamp);
    }
}
Esempio n. 5
0
static vbi_bool
decode_frame			(const vbi_sliced *	sliced,
				 unsigned int		n_lines,
				 const uint8_t *	raw,
				 const vbi_sampling_par *sp,
				 double			sample_time,
				 int64_t		stream_time)
{
	raw = raw;
	sp = sp;
	stream_time = stream_time; /* unused */

	vbi_decode (vbi, sliced, n_lines, sample_time);

	/* xevent (1e6 / 30); */

	return TRUE;
}
Esempio n. 6
0
static vbi_bool
gst_teletextdec_convert (vbi_dvb_demux * dx,
    gpointer user_data, const vbi_sliced * sliced, guint n_lines, gint64 pts)
{
  gdouble sample_time;
  vbi_sliced *s;

  GstTeletextDec *teletext = GST_TELETEXTDEC (user_data);

  GST_DEBUG_OBJECT (teletext, "Converting %u lines to decode", n_lines);

  sample_time = pts * (1 / 90000.0);

  s = g_memdup (sliced, n_lines * sizeof (vbi_sliced));
  vbi_decode (teletext->decoder, s, n_lines, sample_time);
  g_free (s);

  return GST_FLOW_OK;
}
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;
}
Esempio n. 8
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;
}
Esempio n. 9
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;

    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;
}
Esempio n. 10
0
void
VBIDecoder::decode(PES_packet& pes)
{
    unsigned char* buf = pes.PES_packet_data;
    int len = pes.PES_packet_data_length;
    ScanlineMask mask;
    unsigned char* ptr = buf + 4; // assume we'll find magic cookie
    int i;
    vbi_sliced sliced_array[36];
    vbi_sliced* sliced = sliced_array;
    vbi_sliced* sliced_end;

    // Look for one of the magic cookies identifying this buffer
    // as VBI data captured by the ivtv driver.
    if (memcmp(buf, "itv0", 4) == 0)
    { 
        memcpy(&mask, ptr, 8);
        ptr += 8;
    }
    else if (memcmp(buf, "ITV0", 4) == 0)
    {
        mask.words[0] = 0xffffffff;
        mask.words[1] = 0xf;
    }
    else
        return;

    if (verbose > 1)
        fprintf(fplog, "VBI: time=%.4f len=%d mask=%#llx\n",
            (double)currTimestamp, len, (unsigned long long)mask.llword);

    for (i = 0; i < 36; i++)
    {
        if (FD_ISSET(i, &mask.bits))
        {
            // We'll adjust the value of line later when we know the type
            sliced->line = i;
            sliced++;
            FD_CLR(i, &mask.bits);
        }
        // Optimization, skip to next word when this word is zero
        if (i < 32 && mask.words[0] == 0)
            i = 31;
        if (i >= 32 && mask.words[1] == 0)
            break;
    }
    sliced_end = sliced;

    sliced = sliced_array;
    for (unsigned char* end = buf + len; ptr+43 <= end; ptr += 43, sliced++)
    {
        if (sliced == sliced_end)
        {
            if (verbose > 1)
                fprintf(fplog, "Have more scanlines than bits in mask!\n");
            break;
        }
        int type = *ptr;
        // If line is < 18, it must be a field 1 scanline, just add 6
        // Otherwise, it depends on ivtv type
        if (sliced->line < 18)
            sliced->line += 6;
        else
        {
            if (type == IVTV_SLICED_TYPE_CC) // assume NTSC 525 scanlines
            {
                // 263 = 525/2+1
                sliced->line += (263-18+6);
            }
            else // assume PAL 625 scanlines
            {
                // 313 = 625/2+1
                sliced->line += (313-18+6);
            }
        }
        // set sliced->id based on type
        switch (type)
        {
        // Teletext (uses lines 6-22 for PAL)
        case IVTV_SLICED_TYPE_TELETEXT:
            sliced->id = VBI_SLICED_TELETEXT_B;
            break;

        // Closed Captions (line 21 NTSC)
        case IVTV_SLICED_TYPE_CC:
            sliced->id = VBI_SLICED_CAPTION_525;
            break;

        // Wide Screen Signal (line 23 PAL)
        case IVTV_SLICED_TYPE_WSS:
            sliced->id = VBI_SLICED_WSS_625; // VBI_SLICED_WSS_CPR1204?
            break;

        // Video Programming System (PAL) (line 16)
        case IVTV_SLICED_TYPE_VPS:
            sliced->id = VBI_SLICED_VPS;
            break;
        }

        // Copy the ivtv data to the vbi_sliced structure
        memcpy(sliced->data, ptr+1, 42);

        if (verbose > 1)
        {
            fprintf(fplog, "   ivtv-type=%#x line=%d zvbi-id=%#x", type, sliced->line, sliced->id);
            unsigned char* p = ptr+1;

            int n = (type == IVTV_SLICED_TYPE_CC) ? 2 : 42;
            for (i = 0; i < n; i++, p++)
            {
                fprintf(fplog, " %02x", *p);
                int c = (*p) & 0x7f;
                if (0x20 <= c && c <= 0x7f)
                    fprintf(fplog, "(%c)", c);
            }

            putc('\n', fplog);
        }
    }
    if (verbose && sliced != sliced_end)
    {
        fprintf(fplog, "Have fewer scanlines than bits in mask!\n");
    }
    if (skipVBI > 0)
    {
        if (verbose)
            fprintf(fplog, "Skip\n");
        skipVBI--;
        return;
    }

    if (verbose > 1)
        fflush(fplog);

    // vbi_decode is very fussy about timestamps
    // if the difference between the previous time and the current time
    // is less than 0.025or greater than 0.050, it will blank the page
    // To keep it happy we give it timestamps that won't cause it
    // to ignore valid data just because the timestamps provided by
    // the ivtv driver don't quite match its expectations.
    decoderTimestamp += 0.03;
    vbi_decode(decoder, sliced_array, sliced - sliced_array, decoderTimestamp);
}
Esempio n. 11
0
File: zvbi.c Progetto: etix/vlc
/*****************************************************************************
 * 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;
}
Esempio n. 12
0
File: zvbi.c Progetto: Flameeyes/vlc
/*****************************************************************************
 * 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;
}