Skip to content
Naohiro KORIYAMA edited this page Aug 18, 2014 · 15 revisions

The followings are sample codes using aribb24 library work on OS X 10.9 and Windows 8.1, maybe work on the other OSes.

decoder_sample.c SampleOutput

// gcc -std=gnu99 decoder_sample.c `pkg-config aribb24 --cflags --libs --static`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <aribb24/aribb24.h>
#include <aribb24/decoder.h>

static char* decode_aribstring( arib_instance_t *p_instance, const unsigned char *psz_instring);

int main( int argc, char** argv )
{
    arib_instance_t *p_instance;

    // argument of arib_instance_new, void *p_opaque, is used by 
    // messages_callback.
    // if you don't register messages_callback or don't use it in
    // messages_callback, you can set NULL.
    p_instance = arib_instance_new ( NULL );
    if( !p_instance )
        return -1;

    char* psz_outstring = NULL;

    unsigned char instring[] = "\x1b\x7c\xda\xeb\xbd\xca\x0e\x34\x0f\x21\x21\x21\x74\x0e\x31\x38";
    psz_outstring = decode_aribstring( p_instance, instring );
    if( psz_outstring )
    {
        // ペルソナ4 #18
        fprintf( stdout, "%s\n", psz_outstring );
        free( psz_outstring );
    }

    unsigned char instring2[] = "\x4d\x45\x38\x51\x21\x5f\x4b\x4d\x0e\x53\x53\x0f\x21\x21\x21\x74\x0e\x35\x0f\x1b\x24\x3b\x7a\x56";
    psz_outstring = decode_aribstring( p_instance, instring2 );
    if( psz_outstring )
    {
        // 妖狐×僕SS #5[字]
        fprintf( stdout, "%s\n", psz_outstring );
        free( psz_outstring );
    }

    // you must call arib_instance_destroy when the program finished.
    arib_instance_destroy( p_instance );
}

// decode JIS 8-bit character to UTF-8 characters.
static char* decode_aribstring( arib_instance_t *p_instance, const unsigned char *psz_instring)
{
    if( !psz_instring )
    {
        return NULL;
    }
    size_t i_in = strlen( (const char*)psz_instring );

    arib_decoder_t *p_decoder = arib_get_decoder( p_instance );
    if ( !p_decoder )
        return NULL;

    size_t i_out = i_in * 4;
    char *psz_outstring = (char*) calloc( i_out + 1, sizeof(char) );

    arib_initialize_decoder( p_decoder );
    i_out = arib_decode_buffer( p_decoder,
            psz_instring, i_in,
            psz_outstring, i_out );
    arib_finalize_decoder( p_decoder );

    return psz_outstring;
}

parser_sample.c TestPESData SampleOutput

// gcc -std=gnu99 parser_sample.c `pkg-config aribb24 --cflags --libs --static`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <aribb24/aribb24.h>
#include <aribb24/parser.h>
#include <aribb24/decoder.h>

static size_t count_lines( const char *psz_file_path );
static uint8_t* load_pes_data( const char *psz_file_path, size_t i_data_size );
static void process_stream( arib_instance_t *p_instance, const void* p_data, size_t i_data_size );
static void render( arib_parser_t *p_parser, arib_decoder_t *p_arib_decoder );
static void message_callback_hander( void *p_opaque, const char *psz_messages );

int main( int argc, char** argv )
{
    arib_instance_t *p_instance;

    if( argc < 2 )
    {
        fprintf( stderr, "Usage: %s pes_data_file\n", argv[0] );
        exit( EXIT_FAILURE );
    }

    char* psz_file_path = argv[1];
    int lines = count_lines( psz_file_path );
    size_t i_data_size = lines * sizeof(uint8_t); 
    uint8_t *p_data = load_pes_data( psz_file_path, i_data_size );
    if( !p_data )
    {
        fprintf( stderr, "cannot load data.\n" );
        exit( EXIT_FAILURE );
    }

    // argument of arib_instance_new, void *p_opaque, is used by 
    // messages_callback.
    // if you don't register messages_callback or don't use it in
    // messages_callback, you can set NULL.
    p_instance = arib_instance_new ( NULL );
    if( !p_instance )
        exit( EXIT_FAILURE );

    // Specify base path.
    // - base_path/drcs_conv.ini
    //   If this file exists, convert drcs to UTF-8. 
    // - base_path/data
    //   In this directory, DRCS images are stored like [image md5hash].png.
    arib_set_base_path( p_instance, ".");

    // If you register message callback, you can get log messages
    // from aribb24. This is not mandatory.
    arib_register_messages_callback( p_instance, message_callback_hander );

    process_stream( p_instance, p_data, i_data_size );

    // you must call arib_instance_destroy when the program finished.
    arib_instance_destroy( p_instance );

    free( p_data );

    return EXIT_SUCCESS;
}

static size_t count_lines( const char *psz_file_path )
{
    size_t lines = 0;
    FILE* fp;

    if( (fp = fopen( psz_file_path, "r" )) == NULL )
    {
        fprintf( stderr, "Cannot open file [%s].\n", psz_file_path );
        exit( EXIT_FAILURE );
    }

    while(!feof(fp))
    {
       char ch = fgetc(fp);
       if(ch == '\n')
       {
           lines++;
       }
    }

    fclose( fp );

    return lines;
}

static uint8_t* load_pes_data( const char *psz_file_path, size_t i_data_size )
{
    uint8_t *p_data = (uint8_t*) malloc( i_data_size );
    if( !p_data )
    {
        exit( EXIT_FAILURE );
    }

    FILE* fp;
    if( (fp = fopen( psz_file_path, "r" )) == NULL )
    {
        fprintf( stderr, "Cannot open file [%s].\n", psz_file_path );
        free( p_data );
        exit( EXIT_FAILURE );
    }

    unsigned int index = 0;
    char buf[] = "00\n";
    while( fgets( buf, sizeof(buf), fp ) != NULL )
    {
        p_data[index++] = (uint8_t)strtol( buf, NULL, 16 );
    }

    fclose( fp );

    return p_data;
}

static void process_stream( arib_instance_t *p_instance, const void* p_data, size_t i_data_size )
{
    arib_parser_t *p_parser = arib_get_parser( p_instance );
    arib_decoder_t *p_decoder = arib_get_decoder( p_instance );

    if ( p_parser && p_decoder )
    {
        arib_parse_pes( p_parser, p_data, i_data_size );

        render( p_parser, p_decoder );
    }

    return;
}

static void render( arib_parser_t *p_parser, arib_decoder_t *p_arib_decoder )
{
    size_t i_data_size;
    // get parsed data
    const unsigned char *psz_data = arib_parser_get_data( p_parser, &i_data_size );
    if( !psz_data || !i_data_size )
        return;

    size_t i_subtitle_size = i_data_size * 4;
    char* psz_subtitle = (char*) calloc( i_subtitle_size + 1, sizeof(*psz_subtitle) );
    if( psz_subtitle == NULL )
    {
        return;
    }

    // a_profile : full seg
    // c_profile : one seg
    arib_initialize_decoder_a_profile( p_arib_decoder );
    //arib_initialize_decoder_c_profile( p_arib_decoder );
    
    i_subtitle_size = arib_decode_buffer( p_arib_decoder,
                                          psz_data,
                                          i_data_size,
                                          psz_subtitle,
                                          i_subtitle_size );

    fprintf( stdout, "psz_subtitle: [%s]\n", psz_subtitle );

    // arib_buf_region_t contains display information.
    for( const arib_buf_region_t *p_buf_region = arib_decoder_get_regions( p_arib_decoder ); p_buf_region; p_buf_region = p_buf_region->p_next )
    {
        int i_size = p_buf_region->p_end - p_buf_region->p_start;
        char *psz_text = (char*) calloc( i_size + 1, sizeof(char) );
        if( psz_text == NULL )
        {
            goto malloc_failed;
        }
        strncpy(psz_text, p_buf_region->p_start, i_size);
        psz_text[i_size] = '\0';

        fprintf( stdout, "psz_text: [%s]\n", psz_text );
        fprintf( stdout, "i_foreground_color: [0x%x]\n", p_buf_region->i_foreground_color );
        fprintf( stdout, "i_background_color: [0x%x]\n", p_buf_region->i_background_color );
        fprintf( stdout, "i_planewidth: [%d]\n", p_buf_region->i_planewidth );
        fprintf( stdout, "i_planeheight: [%d]\n", p_buf_region->i_planeheight );
        fprintf( stdout, "i_fontwidth: [%d]\n", p_buf_region->i_fontwidth );
        fprintf( stdout, "i_fontheight: [%d]\n", p_buf_region->i_fontheight );
        fprintf( stdout, "i_charleft: [%d]\n", p_buf_region->i_charleft );
        
        free( psz_text );
    }

malloc_failed:
    arib_finalize_decoder( p_arib_decoder );
    free( psz_subtitle );

    return;
}

// This callback is called by function arib_log in aribb24.
static void message_callback_hander( void *p_opaque, const char *psz_messages )
{
    // you can use p_opaque like the following:
    // decoder_t *p_dec = ( decoder_t * ) p_opaque;
    // msg_Dbg( p_dec, "%s", psz_message );

    fprintf( stderr, "debug: %s\n", psz_messages );
}
Clone this wiki locally