/* PSResynch: resynch on a system startcode * It doesn't skip more than 512 bytes * -1 -> error, 0 -> not synch, 1 -> ok */ static int ps_pkt_resynch( stream_t *s, int format, bool b_pack ) { const uint8_t *p_peek; int i_peek; int i_skip; if( vlc_stream_Peek( s, &p_peek, 4 ) < 4 ) { return -1; } if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 && p_peek[3] >= PS_STREAM_ID_END_STREAM ) { return 1; } if( ( i_peek = vlc_stream_Peek( s, &p_peek, 512 ) ) < 4 ) { return -1; } i_skip = 0; for( ;; ) { if( i_peek < 4 ) { break; } /* Handle mid stream 24 bytes padding+CRC creating emulated sync codes with incorrect PES sizes and frelling up to UINT16_MAX bytes followed by 24 bytes CDXA Header */ if( format == CDXA_PS && i_skip == 0 && i_peek >= 48 ) { const uint8_t cdxasynccode[12] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; if( !memcmp( &p_peek[24], cdxasynccode, 12 ) ) { i_peek -= 48; p_peek += 48; i_skip += 48; continue; } } if( p_peek[0] == 0 && p_peek[1] == 0 && p_peek[2] == 1 && p_peek[3] >= PS_STREAM_ID_END_STREAM && ( !b_pack || p_peek[3] == PS_STREAM_ID_PACK_HEADER ) ) { return vlc_stream_Read( s, NULL, i_skip ) == i_skip ? 1 : -1; } p_peek++; i_peek--; i_skip++; } return vlc_stream_Read( s, NULL, i_skip ) == i_skip ? 0 : -1; }
int DoAcoustIdWebRequest( vlc_object_t *p_obj, acoustid_fingerprint_t *p_data ) { if ( !p_data->psz_fingerprint ) return VLC_SUCCESS; char *psz_url; if( unlikely(asprintf( &psz_url, "https://fingerprint.videolan.org/" "acoustid.php?meta=recordings+tracks+usermeta+" "releases&duration=%d&fingerprint=%s", p_data->i_duration, p_data->psz_fingerprint ) < 1 ) ) return VLC_EGENERIC; msg_Dbg( p_obj, "Querying AcoustID from %s", psz_url ); int i_saved_flags = p_obj->obj.flags; p_obj->obj.flags |= OBJECT_FLAGS_NOINTERACT; stream_t *p_stream = vlc_stream_NewURL( p_obj, psz_url ); free( psz_url ); p_obj->obj.flags = i_saved_flags; if ( p_stream == NULL ) return VLC_EGENERIC; stream_t *p_chain = vlc_stream_FilterNew( p_stream, "inflate" ); if( p_chain ) p_stream = p_chain; /* read answer */ char *p_buffer = NULL; int i_ret = 0; for( ;; ) { int i_read = 65536; if( i_ret >= INT_MAX - i_read ) break; p_buffer = realloc_or_free( p_buffer, 1 + i_ret + i_read ); if( unlikely(p_buffer == NULL) ) { vlc_stream_Delete( p_stream ); return VLC_ENOMEM; } i_read = vlc_stream_Read( p_stream, &p_buffer[i_ret], i_read ); if( i_read <= 0 ) break; i_ret += i_read; } vlc_stream_Delete( p_stream ); p_buffer[i_ret] = 0; if ( ParseJson( p_obj, p_buffer, & p_data->results ) ) msg_Dbg( p_obj, "results count == %d", p_data->results.count ); else msg_Dbg( p_obj, "No results" ); free( p_buffer ); return VLC_SUCCESS; }
static ssize_t Read(access_t *access, void *data, size_t size) { access_sys_t *sys = access->p_sys; size_t total = 0; while (total < size) { const uint64_t chunk_end = sys->chunk->cummulated_size + sys->chunk->size; int max = __MIN(__MIN((int64_t)(size - total), (int64_t)(chunk_end - sys->position)), INT_MAX); if (max <= 0) break; int r = sys->s ? vlc_stream_Read(sys->s, data, max) : -1; if (r <= 0) break; total += r; if( data ) data = ((char *)data) + r; sys->position += r; if (sys->position >= chunk_end && Seek(access, sys->position)) break; } return total; }
static ssize_t SkipCallback(struct archive *p_archive, void *p_object, ssize_t i_request) { VLC_UNUSED(p_archive); callback_data_t *p_data = (callback_data_t *) p_object; access_sys_t *p_sys = p_data->p_access->p_sys; ssize_t i_skipped = 0; /* be smart as small seeks converts to reads */ if (p_sys->b_source_canseek) { int64_t i_pos = vlc_stream_Tell(p_sys->p_stream); if (i_pos >=0) vlc_stream_Seek(p_sys->p_stream, i_pos + i_request); i_skipped = vlc_stream_Tell(p_sys->p_stream) - i_pos; } else while(i_request) { int i_skip = __MIN(INT32_MAX, i_request); int i_read = vlc_stream_Read(p_sys->p_stream, NULL, i_skip); if (i_read > 0) i_skipped += i_read; else break; i_request -= i_read; } return i_skipped; }
/***************************************************************************** * I/O wrappers for libavformat *****************************************************************************/ static int IORead( void *opaque, uint8_t *buf, int buf_size ) { demux_t *p_demux = opaque; if( buf_size < 0 ) return -1; int i_ret = vlc_stream_Read( p_demux->s, buf, buf_size ); return i_ret >= 0 ? i_ret : -1; }
/** ************************************************************************** * \brief read something from stream into buffer * \param opaque should be the stream * \param stream stream created by ZipIO_Open * \param buf buffer to read the file * \param size length of this buffer * \return return the number of bytes read (<= size) *****************************************************************************/ static unsigned long ZCALLBACK ZipIO_Read( void *opaque, void *stream, void *buf, unsigned long size ) { (void) stream; stream_t *s = (stream_t*) opaque; return (unsigned long) vlc_stream_Read( s->p_source, buf, (int) size ); }
static gme_err_t ReaderStream (void *data, void *buf, int length) { stream_t *s = data; if (vlc_stream_Read (s, buf, length) < length) return "short read"; return NULL; }
static ssize_t ReadCallback(struct archive *p_archive, void *p_object, const void **pp_buffer) { VLC_UNUSED(p_archive); callback_data_t *p_data = (callback_data_t *) p_object; access_sys_t *p_sys = p_data->p_access->p_sys; *pp_buffer = &p_sys->buffer; return vlc_stream_Read(p_sys->p_stream, &p_sys->buffer, ARCHIVE_READ_SIZE); }
static int vlclua_stream_read( lua_State *L ) { int i_read; stream_t **pp_stream = (stream_t **)luaL_checkudata( L, 1, "stream" ); int n = luaL_checkint( L, 2 ); uint8_t *p_read = malloc( n ); if( !p_read ) return vlclua_error( L ); i_read = vlc_stream_Read( *pp_stream, p_read, n ); if( i_read > 0 ) lua_pushlstring( L, (const char *)p_read, i_read ); else lua_pushnil( L ); free( p_read ); return 1; }
static int vlclua_demux_read( lua_State *L ) { demux_t *p_demux = (demux_t *)vlclua_get_this( L ); const uint8_t *p_read; int n = (int)luaL_checkinteger( L, 1 ); int i_read = vlc_stream_Peek( p_demux->s, &p_read, n ); if( i_read > 0 ) { lua_pushlstring( L, (const char *)p_read, i_read ); int i_seek = vlc_stream_Read( p_demux->s, NULL, i_read ); assert( i_read == i_seek ); } else lua_pushnil( L ); return 1; }
static int vlclua_demux_read( lua_State *L ) { stream_t *s = (stream_t *)vlclua_get_this(L); int n = luaL_checkinteger( L, 1 ); char *buf = malloc(n); if (buf != NULL) { ssize_t val = vlc_stream_Read(s->s, buf, n); if (val > 0) lua_pushlstring(L, buf, val); else lua_pushnil( L ); free(buf); } else lua_pushnil( L ); return 1; }
/** Replacement for luaL_dofile, using VLC's input capabilities */ int vlclua_dofile( vlc_object_t *p_this, lua_State *L, const char *curi ) { char *uri = ToLocaleDup( curi ); if( !strstr( uri, "://" ) ) { int ret = luaL_dofile( L, uri ); free( uri ); return ret; } if( !strncasecmp( uri, "file://", 7 ) ) { int ret = luaL_dofile( L, uri + 7 ); free( uri ); return ret; } stream_t *s = vlc_stream_NewURL( p_this, uri ); if( !s ) { free( uri ); return 1; } int64_t i_size = stream_Size( s ); char *p_buffer = ( i_size > 0 ) ? malloc( i_size ) : NULL; if( !p_buffer ) { // FIXME: read the whole stream until we reach the end (if no size) vlc_stream_Delete( s ); free( uri ); return 1; } int64_t i_read = vlc_stream_Read( s, p_buffer, (int) i_size ); int i_ret = ( i_read == i_size ) ? 0 : 1; if( !i_ret ) i_ret = luaL_loadbuffer( L, p_buffer, (size_t) i_size, uri ); if( !i_ret ) i_ret = lua_pcall( L, 0, LUA_MULTRET, 0 ); vlc_stream_Delete( s ); free( p_buffer ); free( uri ); return i_ret; }
static int AVI_NextChunk( stream_t *s, avi_chunk_t *p_chk ) { avi_chunk_t chk; if( !p_chk ) { if( AVI_ChunkReadCommon( s, &chk ) ) { return VLC_EGENERIC; } p_chk = &chk; } if( p_chk->common.p_father ) { if( p_chk->common.p_father->common.i_chunk_pos + __EVEN( p_chk->common.p_father->common.i_chunk_size ) + 8 < p_chk->common.i_chunk_pos + __EVEN( p_chk->common.i_chunk_size ) + 8 ) { return VLC_EGENERIC; } } bool b_seekable = false; uint64_t i_offset = p_chk->common.i_chunk_pos + __EVEN( p_chk->common.i_chunk_size ) + 8; if ( !vlc_stream_Control(s, STREAM_CAN_SEEK, &b_seekable) && b_seekable ) { return vlc_stream_Seek( s, i_offset ); } else { ssize_t i_read = i_offset - vlc_stream_Tell( s ); return (i_read >=0 && vlc_stream_Read( s, NULL, i_read ) == i_read) ? VLC_SUCCESS : VLC_EGENERIC; } }
static la_int64_t libarchive_skip_cb( libarchive_t* p_arc, void* p_obj, off_t i_request ) { VLC_UNUSED( p_arc ); libarchive_callback_t* p_cb = (libarchive_callback_t*)p_obj; stream_t* p_source = p_cb->p_source; private_sys_t* p_sys = p_cb->p_sys; /* TODO: fix b_seekable_source on libarchive_callback_t */ if( p_sys->b_seekable_source ) { if( vlc_stream_Seek( p_source, vlc_stream_Tell( p_source ) + i_request ) ) return ARCHIVE_FATAL; return i_request; } ssize_t i_read = vlc_stream_Read( p_source, NULL, i_request ); return i_read >= 0 ? i_read : ARCHIVE_FATAL; }
/**************************************************************************** * Stream filters functions ****************************************************************************/ static ssize_t Read( stream_t *s, void *p_read, size_t i_read ) { stream_sys_t *p_sys = s->p_sys; void *p_record = p_read; /* Allocate a temporary buffer for record when no p_read */ if( p_sys->f && !p_record ) p_record = malloc( i_read ); /* */ const ssize_t i_record = vlc_stream_Read( s->p_source, p_record, i_read ); /* Dump read data */ if( p_sys->f ) { if( p_record && i_record > 0 ) Write( s, p_record, i_record ); if( !p_read ) free( p_record ); } return i_record; }
static la_ssize_t libarchive_read_cb( libarchive_t* p_arc, void* p_obj, const void** pp_dst ) { VLC_UNUSED( p_arc ); libarchive_callback_t* p_cb = (libarchive_callback_t*)p_obj; stream_t* p_source = p_cb->p_source; private_sys_t* p_sys = p_cb->p_sys; ssize_t i_ret = vlc_stream_Read( p_source, &p_sys->buffer, sizeof( p_sys->buffer ) ); if( i_ret < 0 ) { archive_set_error( p_sys->p_archive, ARCHIVE_FATAL, "libarchive_read_cb failed = %zd", i_ret ); return ARCHIVE_FATAL; } *pp_dst = &p_sys->buffer; return i_ret; }
/** * Copy data from input stream to dump file. */ static int Demux( demux_t *p_demux ) { sout_access_out_t *out = (void *)p_demux->p_sys; block_t *block = block_Alloc( DUMP_BLOCKSIZE ); if( unlikely(block == NULL) ) return -1; int rd = vlc_stream_Read( p_demux->s, block->p_buffer, DUMP_BLOCKSIZE ); if ( rd <= 0 ) { block_Release( block ); return rd; } block->i_buffer = rd; size_t wr = sout_AccessOutWrite( out, block ); if( wr != (size_t)rd ) { msg_Err( p_demux, "cannot write data" ); return -1; } return 1; }
static int Retrieve( addons_finder_t *p_finder, addon_entry_t *p_entry ) { vlc_mutex_lock( &p_entry->lock ); if ( !p_entry->psz_archive_uri ) { vlc_mutex_unlock( &p_entry->lock ); return VLC_EGENERIC; } char *psz_archive_uri = strdup( p_entry->psz_archive_uri ); vlc_mutex_unlock( &p_entry->lock ); if ( !psz_archive_uri ) return VLC_ENOMEM; /* get archive and parse manifest */ stream_t *p_stream; if ( psz_archive_uri[0] == '/' ) { /* Relative path */ char *psz_uri; if ( ! asprintf( &psz_uri, ADDONS_REPO_SCHEMEHOST"%s", psz_archive_uri ) ) { free( psz_archive_uri ); return VLC_ENOMEM; } p_stream = vlc_stream_NewURL_ND( p_finder, psz_uri ); free( psz_uri ); } else { p_stream = vlc_stream_NewURL_ND( p_finder, psz_archive_uri ); } msg_Dbg( p_finder, "downloading archive %s", psz_archive_uri ); free ( psz_archive_uri ); if ( !p_stream ) return VLC_EGENERIC; /* In case of pf_ reuse */ if ( p_finder->p_sys->psz_tempfile ) { vlc_unlink( p_finder->p_sys->psz_tempfile ); FREENULL( p_finder->p_sys->psz_tempfile ); } p_finder->p_sys->psz_tempfile = tempnam( NULL, "vlp" ); if ( !p_finder->p_sys->psz_tempfile ) { msg_Err( p_finder, "Can't create temp storage file" ); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } FILE *p_destfile = vlc_fopen( p_finder->p_sys->psz_tempfile, "w" ); if( !p_destfile ) { msg_Err( p_finder, "Failed to open addon temp storage file" ); FREENULL(p_finder->p_sys->psz_tempfile); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } char buffer[1<<10]; int i_read = 0; while ( ( i_read = vlc_stream_Read( p_stream, &buffer, 1<<10 ) ) > 0 ) { if ( fwrite( &buffer, i_read, 1, p_destfile ) < 1 ) { msg_Err( p_finder, "Failed to write to Addon file" ); fclose( p_destfile ); vlc_stream_Delete( p_stream ); return VLC_EGENERIC; } } fclose( p_destfile ); vlc_stream_Delete( p_stream ); msg_Dbg( p_finder, "Reading manifest from %s", p_finder->p_sys->psz_tempfile ); char *psz_tempfileuri = vlc_path2uri( p_finder->p_sys->psz_tempfile, NULL ); if ( !psz_tempfileuri ) return VLC_ENOMEM; char *psz_manifest_uri; if ( asprintf( &psz_manifest_uri, "%s#!/manifest.xml", psz_tempfileuri ) < 1 ) { free( psz_tempfileuri ); return VLC_ENOMEM; } p_stream = vlc_stream_NewMRL( p_finder, psz_manifest_uri ); free( psz_manifest_uri ); if ( !p_stream ) { free( psz_tempfileuri ); return VLC_EGENERIC; } vlc_mutex_lock( &p_entry->lock ); int i_ret = ( ParseManifest( p_finder, p_entry, psz_tempfileuri, p_stream ) > 0 ) ? VLC_SUCCESS : VLC_EGENERIC; vlc_mutex_unlock( &p_entry->lock ); free( psz_tempfileuri ); vlc_stream_Delete( p_stream ); return i_ret; }
static int Open(vlc_object_t *object) { demux_t *demux = (demux_t*)object; const uint8_t *peek; if (vlc_stream_Peek(demux->s, &peek, 11) != 11) return VLC_EGENERIC; bool is_stl_25 = !memcmp(&peek[3], "STL25.01", 8); bool is_stl_30 = !memcmp(&peek[3], "STL30.01", 8); if (!is_stl_25 && !is_stl_30) return VLC_EGENERIC; const double fps = is_stl_25 ? 25 : 30; uint8_t header[1024]; if (vlc_stream_Read(demux->s, header, sizeof(header)) != sizeof(header)) { msg_Err(demux, "Incomplete EBU STL header"); return VLC_EGENERIC; } const int cct = ParseInteger(&header[12], 2); const mtime_t program_start = ParseTextTimeCode(&header[256], fps); const int tti_count = ParseInteger(&header[238], 5); msg_Dbg(demux, "Detected EBU STL : CCT=%d TTI=%d start=%8.8s %"PRId64, cct, tti_count, &header[256], program_start); demux_sys_t *sys = xmalloc(sizeof(*sys)); sys->next_date = 0; sys->current = 0; sys->count = 0; sys->index = xcalloc(tti_count, sizeof(*sys->index)); bool comment = false; stl_entry_t *s = &sys->index[0]; s->count = 0; for (int i = 0; i < tti_count; i++) { uint8_t tti[16]; if (vlc_stream_Read(demux->s, tti, 16) != 16 || vlc_stream_Read(demux->s, NULL, 112) != 112) { msg_Warn(demux, "Incomplete EBU STL file"); break; } const int ebn = tti[3]; if (ebn >= 0xf0 && ebn <= 0xfd) continue; if (ebn == 0xfe) continue; if (s->count <= 0) { comment = tti[15] != 0; s->start = ParseTimeCode(&tti[5], fps) - program_start; s->stop = ParseTimeCode(&tti[9], fps) - program_start; s->index = i; } s->count++; if (ebn == 0xff && !comment) s = &sys->index[++sys->count]; if (ebn == 0xff && sys->count < tti_count) s->count = 0; } if (sys->count > 0) vlc_stream_Seek(demux->s, 1024 + 128LL * sys->index[0].index); es_format_t fmt; es_format_Init(&fmt, SPU_ES, VLC_CODEC_EBU_STL); fmt.i_extra = sizeof(header); fmt.p_extra = header; sys->es = es_out_Add(demux->out, &fmt); fmt.i_extra = 0; fmt.p_extra = NULL; es_format_Clean(&fmt); demux->p_sys = sys; demux->pf_demux = Demux; demux->pf_control = Control; return VLC_SUCCESS; }
/***************************************************************************** * Open *****************************************************************************/ static int Open( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; ModPlug_Settings settings; /* We accept file based on extension match */ if( !p_demux->obj.force ) { const char *psz_ext = p_demux->psz_filepath ? strrchr( p_demux->psz_filepath, '.' ) : NULL; if( psz_ext ) psz_ext++; if( Validate( p_demux, psz_ext ) ) { msg_Dbg( p_demux, "MOD validation failed (ext=%s)", psz_ext ? psz_ext : ""); return VLC_EGENERIC; } } const int64_t i_size = stream_Size( p_demux->s ); if( i_size <= 0 || i_size >= MOD_MAX_FILE_SIZE ) return VLC_EGENERIC; p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) ); if( !p_sys ) return VLC_ENOMEM; msg_Dbg( p_demux, "loading complete file (could be long)" ); p_sys->i_data = i_size; p_sys->p_data = vlc_obj_malloc( p_this, p_sys->i_data ); if( unlikely(p_sys->p_data == NULL) ) return VLC_ENOMEM; p_sys->i_data = vlc_stream_Read( p_demux->s, p_sys->p_data, p_sys->i_data ); if( p_sys->i_data <= 0 ) { msg_Err( p_demux, "failed to read the complete file" ); return VLC_EGENERIC; } /* Configure modplug before loading the file */ vlc_mutex_lock( &libmodplug_lock ); ModPlug_GetSettings( &settings ); settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING; settings.mChannels = 2; settings.mBits = 16; settings.mFrequency = 44100; settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; if( var_InheritBool( p_demux, "mod-noisereduction" ) ) settings.mFlags |= MODPLUG_ENABLE_NOISE_REDUCTION; if( var_InheritBool( p_demux, "mod-reverb" ) ) settings.mFlags |= MODPLUG_ENABLE_REVERB; settings.mReverbDepth = var_InheritInteger( p_demux, "mod-reverb-level" ); settings.mReverbDelay = var_InheritInteger( p_demux, "mod-reverb-delay" ); if( var_InheritBool( p_demux, "mod-megabass" ) ) settings.mFlags |= MODPLUG_ENABLE_MEGABASS; settings.mBassAmount = var_InheritInteger( p_demux, "mod-megabass-level" ); settings.mBassRange = var_InheritInteger( p_demux, "mod-megabass-range" ); if( var_InheritBool( p_demux, "mod-surround" ) ) settings.mFlags |= MODPLUG_ENABLE_SURROUND; settings.mSurroundDepth = var_InheritInteger( p_demux, "mod-surround-level" ); settings.mSurroundDelay = var_InheritInteger( p_demux, "mod-surround-delay" ); ModPlug_SetSettings( &settings ); p_sys->f = ModPlug_Load( p_sys->p_data, p_sys->i_data ); vlc_mutex_unlock( &libmodplug_lock ); if( !p_sys->f ) { msg_Err( p_demux, "failed to understand the file" ); return VLC_EGENERIC; } /* init time */ date_Init( &p_sys->pts, settings.mFrequency, 1 ); date_Set( &p_sys->pts, VLC_TICK_0 ); p_sys->i_length = VLC_TICK_FROM_MS( ModPlug_GetLength( p_sys->f ) ); msg_Dbg( p_demux, "MOD loaded name=%s length=%"PRId64"ms", ModPlug_GetName( p_sys->f ), MS_FROM_VLC_TICK( p_sys->i_length ) ); #ifdef WORDS_BIGENDIAN es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 't', 'w', 'o', 's' ) ); #else es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 'a', 'r', 'a', 'w' ) ); #endif p_sys->fmt.audio.i_rate = settings.mFrequency; p_sys->fmt.audio.i_channels = settings.mChannels; p_sys->fmt.audio.i_bitspersample = settings.mBits; p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt ); if( unlikely(p_sys->es == NULL) ) return VLC_ENOMEM; /* Fill p_demux field */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys; return VLC_SUCCESS; }
/***************************************************************************** * Open: check file and initializes structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; const uint8_t *peek; /* XA file heuristic */ if( vlc_stream_Peek( p_demux->s, &peek, 10 ) < 10 ) return VLC_EGENERIC; if( memcmp( peek, "XAI", 4 ) && memcmp( peek, "XAJ", 4 ) && memcmp( peek, "XA\0", 4 ) ) return VLC_EGENERIC; if( GetWLE( peek + 8 ) != 1 ) /* format tag */ return VLC_EGENERIC; demux_sys_t *p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) ); if( unlikely( p_sys == NULL ) ) return VLC_ENOMEM; /* read XA header*/ xa_header_t xa; if( vlc_stream_Read( p_demux->s, &xa, HEADER_LENGTH ) < HEADER_LENGTH ) return VLC_EGENERIC; es_format_t fmt; es_format_Init( &fmt, AUDIO_ES, VLC_CODEC_ADPCM_XA_EA ); msg_Dbg( p_demux, "assuming EA ADPCM audio codec" ); fmt.audio.i_rate = GetDWLE( &xa.nSamplesPerSec ); fmt.audio.i_bytes_per_frame = 15 * GetWLE( &xa.nChannels ); fmt.audio.i_frame_length = FRAME_LENGTH; fmt.audio.i_channels = GetWLE ( &xa.nChannels ); fmt.audio.i_blockalign = fmt.audio.i_bytes_per_frame; fmt.audio.i_bitspersample = GetWLE( &xa.wBitsPerSample ); fmt.i_bitrate = (fmt.audio.i_rate * fmt.audio.i_bytes_per_frame * 8) / fmt.audio.i_frame_length; /* FIXME: better computation */ p_sys->i_data_size = xa.iSize * 15 / 56; /* How many frames per block (1:1 is too CPU intensive) */ p_sys->i_block_frames = fmt.audio.i_rate / (FRAME_LENGTH * 20) + 1; p_sys->i_frame_size = fmt.audio.i_bytes_per_frame; p_sys->i_bitrate = fmt.i_bitrate; msg_Dbg( p_demux, "fourcc: %4.4s, channels: %d, " "freq: %d Hz, bitrate: %dKo/s, blockalign: %d", (char *)&fmt.i_codec, fmt.audio.i_channels, fmt.audio.i_rate, fmt.i_bitrate / 8192, fmt.audio.i_blockalign ); if( fmt.audio.i_rate == 0 || fmt.audio.i_channels == 0 || fmt.audio.i_bitspersample != 16 ) return VLC_EGENERIC; p_sys->p_es = es_out_Add( p_demux->out, &fmt ); if( unlikely(p_sys->p_es == NULL) ) return VLC_ENOMEM; date_Init( &p_sys->pts, fmt.audio.i_rate, 1 ); date_Set( &p_sys->pts, VLC_TICK_0 ); p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys; return VLC_SUCCESS; }
static ssize_t Read( stream_t *s, void *buffer, size_t i_read ) { return vlc_stream_Read( s->p_source, buffer, i_read ); }
static int Open (vlc_object_t *obj) { demux_t *demux = (demux_t *)obj; demux_sys_t *sys = NULL; es_format_t fmt; bool result = false; SidTune *tune = NULL; sidplay2 *player = NULL; ReSIDBuilder *builder = NULL; int64_t size = stream_Size (demux->s); if (size < 4 || size > LONG_MAX) /* We need to load the whole file for sidplay */ return VLC_EGENERIC; const uint8_t *peek; if (vlc_stream_Peek (demux->s, &peek, 4) < 4) return VLC_EGENERIC; /* sidplay2 can read PSID and the newer RSID formats */ if(memcmp(peek,"PSID",4)!=0 && memcmp(peek,"RSID",4)!=0) return VLC_EGENERIC; uint8_t *data = (uint8_t*) malloc(size); if (unlikely (data==NULL)) goto error; if (vlc_stream_Read (demux->s,data,size) < size) { free (data); goto error; } tune = new (std::nothrow) SidTune(0); if (unlikely (tune==NULL)) { free (data); goto error; } result = tune->read (data, size); free (data); if (!result) goto error; player = new (std::nothrow) sidplay2(); if (unlikely(player==NULL)) goto error; sys = (demux_sys_t*) calloc (1, sizeof(demux_sys_t)); if (unlikely(sys==NULL)) goto error; sys->player = player; sys->tune = tune; tune->getInfo (sys->tuneInfo); sys->info = player->info(); sys->config = player->config(); builder = new (std::nothrow) ReSIDBuilder ("ReSID"); if (unlikely(builder==NULL)) goto error; builder->create (sys->info.maxsids); builder->sampling (sys->config.frequency); sys->config.sidEmulation = builder; sys->config.precision = 16; sys->config.playback = (sys->info.channels == 2 ? sid2_stereo : sid2_mono); player->config (sys->config); sys->bytes_per_frame = sys->info.channels * sys->config.precision / 8; sys->block_size = sys->config.frequency / 10 * sys->bytes_per_frame; es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N); fmt.audio.i_channels = sys->info.channels; fmt.audio.i_bitspersample = sys->config.precision; fmt.audio.i_rate = sys->config.frequency; fmt.audio.i_bytes_per_frame = sys->bytes_per_frame; fmt.audio.i_frame_length = fmt.audio.i_bytes_per_frame; fmt.audio.i_blockalign = fmt.audio.i_bytes_per_frame; fmt.i_bitrate = fmt.audio.i_rate * fmt.audio.i_bytes_per_frame; sys->es = es_out_Add (demux->out, &fmt); date_Init (&sys->pts, fmt.audio.i_rate, 1); date_Set (&sys->pts, 0); sys->tune->selectSong (0); result = (sys->player->load (sys->tune) >=0 ); sys->player->fastForward (100); if (!result) goto error; /* Callbacks */ demux->pf_demux = Demux; demux->pf_control = Control; demux->p_sys = sys; return VLC_SUCCESS; error: msg_Err (demux, "An error occurred during sid demuxing" ); delete player; delete builder; delete tune; free (sys); return VLC_EGENERIC; }
char *vlc_stream_ReadLine( stream_t *s ) { stream_priv_t *priv = (stream_priv_t *)s; char *p_line = NULL; int i_line = 0, i_read = 0; /* Let's fail quickly if this is a readdir access */ if( s->pf_read == NULL ) return NULL; for( ;; ) { char *psz_eol; const uint8_t *p_data; int i_data; int64_t i_pos; /* Probe new data */ i_data = vlc_stream_Peek( s, &p_data, STREAM_PROBE_LINE ); if( i_data <= 0 ) break; /* No more data */ /* BOM detection */ i_pos = vlc_stream_Tell( s ); if( i_pos == 0 && i_data >= 2 ) { const char *psz_encoding = NULL; if( !memcmp( p_data, "\xFF\xFE", 2 ) ) { psz_encoding = "UTF-16LE"; priv->text.little_endian = true; } else if( !memcmp( p_data, "\xFE\xFF", 2 ) ) { psz_encoding = "UTF-16BE"; } /* Open the converter if we need it */ if( psz_encoding != NULL ) { msg_Dbg( s, "UTF-16 BOM detected" ); priv->text.char_width = 2; priv->text.conv = vlc_iconv_open( "UTF-8", psz_encoding ); if( priv->text.conv == (vlc_iconv_t)-1 ) msg_Err( s, "iconv_open failed" ); } } if( i_data % priv->text.char_width ) { /* keep i_char_width boundary */ i_data = i_data - ( i_data % priv->text.char_width ); msg_Warn( s, "the read is not i_char_width compatible"); } if( i_data == 0 ) break; /* Check if there is an EOL */ if( priv->text.char_width == 1 ) { /* UTF-8: 0A <LF> */ psz_eol = memchr( p_data, '\n', i_data ); if( psz_eol == NULL ) /* UTF-8: 0D <CR> */ psz_eol = memchr( p_data, '\r', i_data ); } else { const uint8_t *p_last = p_data + i_data - priv->text.char_width; uint16_t eol = priv->text.little_endian ? 0x0A00 : 0x00A0; assert( priv->text.char_width == 2 ); psz_eol = NULL; /* UTF-16: 000A <LF> */ for( const uint8_t *p = p_data; p <= p_last; p += 2 ) { if( U16_AT( p ) == eol ) { psz_eol = (char *)p + 1; break; } } if( psz_eol == NULL ) { /* UTF-16: 000D <CR> */ eol = priv->text.little_endian ? 0x0D00 : 0x00D0; for( const uint8_t *p = p_data; p <= p_last; p += 2 ) { if( U16_AT( p ) == eol ) { psz_eol = (char *)p + 1; break; } } } } if( psz_eol ) { i_data = (psz_eol - (char *)p_data) + 1; p_line = realloc_or_free( p_line, i_line + i_data + priv->text.char_width ); /* add \0 */ if( !p_line ) goto error; i_data = vlc_stream_Read( s, &p_line[i_line], i_data ); if( i_data <= 0 ) break; /* Hmmm */ i_line += i_data - priv->text.char_width; /* skip \n */; i_read += i_data; /* We have our line */ break; } /* Read data (+1 for easy \0 append) */ p_line = realloc_or_free( p_line, i_line + STREAM_PROBE_LINE + priv->text.char_width ); if( !p_line ) goto error; i_data = vlc_stream_Read( s, &p_line[i_line], STREAM_PROBE_LINE ); if( i_data <= 0 ) break; /* Hmmm */ i_line += i_data; i_read += i_data; if( i_read >= STREAM_LINE_MAX ) goto error; /* line too long */ } if( i_read > 0 ) { memset(p_line + i_line, 0, priv->text.char_width); i_line += priv->text.char_width; /* the added \0 */ if( priv->text.char_width > 1 ) { int i_new_line = 0; size_t i_in = 0, i_out = 0; const char * p_in = NULL; char * p_out = NULL; char * psz_new_line = NULL; /* iconv */ /* UTF-8 needs at most 150% of the buffer as many as UTF-16 */ i_new_line = i_line * 3 / 2; psz_new_line = malloc( i_new_line ); if( psz_new_line == NULL ) goto error; i_in = (size_t)i_line; i_out = (size_t)i_new_line; p_in = p_line; p_out = psz_new_line; if( vlc_iconv( priv->text.conv, &p_in, &i_in, &p_out, &i_out ) == (size_t)-1 ) { msg_Err( s, "iconv failed" ); msg_Dbg( s, "original: %d, in %d, out %d", i_line, (int)i_in, (int)i_out ); } free( p_line ); p_line = psz_new_line; i_line = (size_t)i_new_line - i_out; /* does not include \0 */ } /* Remove trailing LF/CR */ while( i_line >= 2 && ( p_line[i_line-2] == '\r' || p_line[i_line-2] == '\n') ) i_line--; /* Make sure the \0 is there */ p_line[i_line-1] = '\0'; return p_line; } error: /* We failed to read any data, probably EOF */ free( p_line ); /* */ if( priv->text.conv != (vlc_iconv_t)(-1) ) { vlc_iconv_close( priv->text.conv ); priv->text.conv = (vlc_iconv_t)(-1); } return NULL; }
/***************************************************************************** * Open: check file and initializes structures *****************************************************************************/ static int Open( vlc_object_t * p_this ) { demux_t *p_demux = (demux_t*)p_this; int i_size; bool b_matched = false; if( IsMxpeg( p_demux->s ) && !p_demux->obj.force ) // let avformat handle this case return VLC_EGENERIC; demux_sys_t *p_sys = malloc( sizeof( demux_sys_t ) ); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; p_demux->pf_control = Control; p_demux->p_sys = p_sys; p_sys->p_es = NULL; p_sys->i_time = VLC_TS_0; p_sys->i_level = 0; p_sys->psz_separator = NULL; p_sys->i_frame_size_estimate = 15 * 1024; char *content_type = stream_ContentType( p_demux->s ); if ( content_type ) { //FIXME: this is not fully match to RFC char* boundary = strstr( content_type, "boundary=" ); if( boundary ) { boundary += strlen( "boundary=" ); size_t len = strlen( boundary ); if( len > 2 && boundary[0] == '"' && boundary[len-1] == '"' ) { boundary[len-1] = '\0'; boundary++; } p_sys->psz_separator = strdup( boundary ); if( !p_sys->psz_separator ) { free( content_type ); goto error; } } free( content_type ); } b_matched = CheckMimeHeader( p_demux, &i_size); if( b_matched ) { p_demux->pf_demux = MimeDemux; vlc_stream_Read( p_demux->s, NULL, i_size ); } else if( i_size == 0 ) { /* 0xffd8 identify a JPEG SOI */ if( p_sys->p_peek[0] == 0xFF && p_sys->p_peek[1] == 0xD8 ) { msg_Dbg( p_demux, "JPEG SOI marker detected" ); p_demux->pf_demux = MjpgDemux; p_sys->i_level++; } else { goto error; } } else { goto error; } /* Frame rate */ float f_fps = var_InheritFloat( p_demux, "mjpeg-fps" ); p_sys->i_still_end = 0; if( demux_IsPathExtension( p_demux, ".jpeg" ) || demux_IsPathExtension( p_demux, ".jpg" ) ) { /* Plain JPEG file = single still picture */ p_sys->b_still = true; if( f_fps == 0.f ) /* Defaults to 1fps */ f_fps = 1.f; } else p_sys->b_still = false; p_sys->i_frame_length = f_fps ? (CLOCK_FREQ / f_fps) : 0; es_format_Init( &p_sys->fmt, VIDEO_ES, 0 ); p_sys->fmt.i_codec = VLC_CODEC_MJPG; p_sys->p_es = es_out_Add( p_demux->out, &p_sys->fmt ); return VLC_SUCCESS; error: free( p_sys->psz_separator ); free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Open *****************************************************************************/ static int OpenCommon( vlc_object_t *p_this, bool b_force ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; const uint8_t *p_peek; ssize_t i_peek = 0; ssize_t i_offset = 0; ssize_t i_skip = 0; unsigned i_max_packets = PS_PACKET_PROBE; int format = MPEG_PS; int i_mux_rate = 0; vlc_tick_t i_length = VLC_TICK_INVALID; i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 ); if( i_peek < 16 ) { msg_Dbg( p_demux, "cannot peek" ); return VLC_EGENERIC; } if( !memcmp( p_peek, "PSMF", 4 ) && (GetDWBE( &p_peek[4] ) & 0x30303030) == 0x30303030 ) { i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 100 ); if( i_peek < 100 ) return VLC_EGENERIC; i_skip = i_offset = GetWBE( &p_peek[10] ); format = PSMF_PS; msg_Info( p_demux, "Detected PSMF-PS header"); i_mux_rate = GetDWBE( &p_peek[96] ); if( GetDWBE( &p_peek[86] ) > 0 ) i_length = vlc_tick_from_samples( GetDWBE( &p_peek[92] ), GetDWBE( &p_peek[86] )); } else if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) ) { format = CDXA_PS; i_max_packets = 0; /* We can't probe here */ i_skip = CDXA_HEADER_SIZE; msg_Info( p_demux, "Detected CDXA-PS" ); /* FIXME: have a proper way to decap CD sectors or make an access stream filter */ } else if( b_force ) { msg_Warn( p_demux, "this does not look like an MPEG PS stream, " "continuing anyway" ); i_max_packets = 0; } for( unsigned i=0; i<i_max_packets; i++ ) { if( i_peek < i_offset + 16 ) { i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_offset + 16 ); if( i_peek < i_offset + 16 ) return VLC_EGENERIC; } const uint8_t startcode[3] = { 0x00, 0x00, 0x01 }; const uint8_t *p_header = &p_peek[i_offset]; if( memcmp( p_header, startcode, 3 ) || ( (p_header[3] & 0xB0) != 0xB0 && !(p_header[3] >= 0xC0 && p_header[3] <= 0xEF) && p_header[3] != PS_STREAM_ID_EXTENDED && p_header[3] != PS_STREAM_ID_DIRECTORY ) ) return VLC_EGENERIC; ssize_t i_pessize = ps_pkt_size( p_header, 16 ); if( i_pessize < 5 ) return VLC_EGENERIC; i_offset += i_pessize; } if( i_skip > 0 && !p_demux->b_preparsing && vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip ) return VLC_EGENERIC; /* Fill p_demux field */ p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_demux->pf_demux = Demux; p_demux->pf_control = Control; /* Init p_sys */ p_sys->i_mux_rate = i_mux_rate; p_sys->i_pack_scr = VLC_TICK_INVALID; p_sys->i_first_scr = VLC_TICK_INVALID; p_sys->i_scr = VLC_TICK_INVALID; p_sys->i_scr_track_id = 0; p_sys->i_length = i_length; p_sys->i_current_pts = VLC_TICK_INVALID; p_sys->i_time_track_index = -1; p_sys->i_aob_mlp_count = 0; p_sys->i_start_byte = i_skip; p_sys->i_lastpack_byte = i_skip; p_sys->b_lost_sync = false; p_sys->b_have_pack = false; p_sys->b_bad_scr = false; p_sys->b_seekable = false; p_sys->format = format; p_sys->current_title = 0; p_sys->current_seekpoint = 0; p_sys->updates = 0; vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable ); ps_psm_init( &p_sys->psm ); ps_track_init( p_sys->tk ); /* TODO prescanning of ES */ return VLC_SUCCESS; }
static ssize_t Read( stream_t *p_stream, void *p_buf, size_t i_toread ) { stream_sys_t *p_sys = p_stream->p_sys; uint8_t *p_dst = p_buf; int i_total_read = 0; int i_ret; if ( !i_toread ) return -1; /* Use data from previous reads */ size_t i_fromremain = RemainRead( p_stream, p_dst, i_toread ); i_total_read += i_fromremain; p_dst += i_fromremain; i_toread -= i_fromremain; while ( i_toread ) { /* make use of the existing buffer, overwritten by decoder data later */ int i_srcread = vlc_stream_Read( p_stream->s, p_dst, i_toread ); if ( i_srcread > 0 ) { ARIB_STD_B25_BUFFER putbuf = { p_dst, i_srcread }; i_ret = p_sys->p_b25->put( p_sys->p_b25, &putbuf ); if ( i_ret < 0 ) { msg_Err( p_stream, "decoder put failed: %s", GetErrorMessage( i_ret, b25_errors ) ); return 0; } } else { if ( i_srcread < 0 ) msg_Err( p_stream, "Can't read %lu bytes from source stream: %d", i_toread, i_srcread ); return 0; } ARIB_STD_B25_BUFFER getbuf; i_ret = p_sys->p_b25->get( p_sys->p_b25, &getbuf ); if ( i_ret < 0 ) { msg_Err( p_stream, "decoder get failed: %s", GetErrorMessage( i_ret, b25_errors ) ); return 0; } if ( (size_t)getbuf.size > i_toread ) { /* Hold remaining data for next call */ RemainAdd( p_stream, getbuf.data + i_toread, getbuf.size - i_toread ); } int consume = __MIN( (size_t)getbuf.size, i_toread ); memcpy( p_dst, getbuf.data, consume ); i_total_read += consume; p_dst += consume; i_toread -= consume; } return i_total_read; }
/***************************************************************************** * Open: check file and initializes structures *****************************************************************************/ static int Open( vlc_object_t *p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; uint8_t hdr[20]; const uint8_t *p_peek; int i_cat; if( vlc_stream_Peek( p_demux->s , &p_peek, 4 ) < 4 ) return VLC_EGENERIC; if( memcmp( p_peek, ".snd", 4 ) ) return VLC_EGENERIC; /* skip signature */ if( vlc_stream_Read( p_demux->s, NULL, 4 ) < 4 ) return VLC_EGENERIC; /* read header */ if( vlc_stream_Read( p_demux->s, hdr, 20 ) < 20 ) { msg_Err( p_demux, "cannot read" ); return VLC_EGENERIC; } if( GetDWBE( &hdr[0] ) < 24 ) { msg_Err( p_demux, "invalid file" ); return VLC_EGENERIC; } p_sys = malloc( sizeof (*p_sys) ); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; p_sys->i_time = 0; p_sys->i_header_size = GetDWBE( &hdr[0] ); /* skip extra header data */ if( p_sys->i_header_size > 24 ) { #if (SSIZE_MAX <= INT32_MAX) if( p_sys->i_header_size > SSIZE_MAX ) goto error; #endif size_t skip = p_sys->i_header_size - 24; if( vlc_stream_Read( p_demux->s, NULL, skip ) < (ssize_t)skip ) goto error; } /* init fmt */ es_format_Init( &p_sys->fmt, AUDIO_ES, 0 ); p_sys->fmt.audio.i_rate = GetDWBE( &hdr[12] ); p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] ); #if 0 p_sys->au.i_header_size = GetDWBE( &p_sys->au.i_header_size ); p_sys->au.i_data_size = GetDWBE( &p_sys->au.i_data_size ); p_sys->au.i_encoding = GetDWBE( &p_sys->au.i_encoding ); p_sys->au.i_sample_rate = GetDWBE( &p_sys->au.i_sample_rate ); p_sys->au.i_channels = GetDWBE( &p_sys->au.i_channels ); #endif switch( GetDWBE( &hdr[8] ) ) { case AU_ALAW_8: /* 8-bit ISDN A-law */ p_sys->fmt.i_codec = VLC_CODEC_ALAW; p_sys->fmt.audio.i_bitspersample = 8; p_sys->fmt.audio.i_blockalign = 1 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_MULAW_8: /* 8-bit ISDN u-law */ p_sys->fmt.i_codec = VLC_CODEC_MULAW; p_sys->fmt.audio.i_bitspersample = 8; p_sys->fmt.audio.i_blockalign = 1 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_LINEAR_8: /* 8-bit linear PCM */ p_sys->fmt.i_codec = VLC_CODEC_S8; p_sys->fmt.audio.i_bitspersample = 8; p_sys->fmt.audio.i_blockalign = 1 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_LINEAR_16: /* 16-bit linear PCM */ p_sys->fmt.i_codec = VLC_CODEC_S16B; p_sys->fmt.audio.i_bitspersample = 16; p_sys->fmt.audio.i_blockalign = 2 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_LINEAR_24: /* 24-bit linear PCM */ p_sys->fmt.i_codec = VLC_CODEC_S24B; p_sys->fmt.audio.i_bitspersample = 24; p_sys->fmt.audio.i_blockalign = 3 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_LINEAR_32: /* 32-bit linear PCM */ p_sys->fmt.i_codec = VLC_CODEC_S32B; p_sys->fmt.audio.i_bitspersample = 32; p_sys->fmt.audio.i_blockalign = 4 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_FLOAT: /* 32-bit IEEE floating point */ p_sys->fmt.i_codec = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT ); p_sys->fmt.audio.i_bitspersample = 32; p_sys->fmt.audio.i_blockalign = 4 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_DOUBLE: /* 64-bit IEEE floating point */ p_sys->fmt.i_codec = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE ); p_sys->fmt.audio.i_bitspersample = 64; p_sys->fmt.audio.i_blockalign = 8 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_PCM; break; case AU_ADPCM_G721: /* 4-bit CCITT g.721 ADPCM */ p_sys->fmt.i_codec = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 ); p_sys->fmt.audio.i_bitspersample = 0; p_sys->fmt.audio.i_blockalign = 0 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_ADPCM; break; case AU_ADPCM_G722: /* CCITT g.722 ADPCM */ p_sys->fmt.i_codec = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 ); p_sys->fmt.audio.i_bitspersample = 0; p_sys->fmt.audio.i_blockalign = 0 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_ADPCM; break; case AU_ADPCM_G723_3: /* CCITT g.723 3-bit ADPCM */ p_sys->fmt.i_codec = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 ); p_sys->fmt.audio.i_bitspersample = 0; p_sys->fmt.audio.i_blockalign = 0 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_ADPCM; break; case AU_ADPCM_G723_5: /* CCITT g.723 5-bit ADPCM */ p_sys->fmt.i_codec = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 ); p_sys->fmt.audio.i_bitspersample = 0; p_sys->fmt.audio.i_blockalign = 0 * p_sys->fmt.audio.i_channels; i_cat = AU_CAT_ADPCM; break; default: msg_Warn( p_demux, "unknown encoding=0x%x", GetDWBE( &hdr[8] ) ); p_sys->fmt.audio.i_bitspersample = 0; p_sys->fmt.audio.i_blockalign = 0; i_cat = AU_CAT_UNKNOWN; break; } p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate * p_sys->fmt.audio.i_channels * p_sys->fmt.audio.i_bitspersample; if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM ) { msg_Err( p_demux, "unsupported codec/type (Please report it)" ); goto error; } if( p_sys->fmt.audio.i_rate == 0 ) { msg_Err( p_demux, "invalid samplerate: 0" ); goto error; } /* add the es */ p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt ); /* calculate 50ms frame size/time */ unsigned i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 ); p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels * ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 ); if( p_sys->fmt.audio.i_blockalign > 0 ) { unsigned mod = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign; if( mod != 0 ) { p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - mod; } } p_sys->i_frame_length = (mtime_t)1000000 * (mtime_t)i_samples / (mtime_t)p_sys->fmt.audio.i_rate; p_demux->p_sys = p_sys; p_demux->pf_demux = Demux; p_demux->pf_control = Control; return VLC_SUCCESS; error: free( p_sys ); return VLC_EGENERIC; }
/***************************************************************************** * Handshake : Init audioscrobbler connection *****************************************************************************/ static int Handshake(intf_thread_t *p_this) { char *psz_username, *psz_password; char *psz_scrobbler_url; time_t timestamp; char psz_timestamp[21]; struct md5_s p_struct_md5; stream_t *p_stream; char *psz_handshake_url; uint8_t p_buffer[1024]; char *p_buffer_pos; int i_ret; char *psz_url; intf_thread_t *p_intf = (intf_thread_t*) p_this; intf_sys_t *p_sys = p_this->p_sys; psz_username = var_InheritString(p_this, "lastfm-username"); psz_password = var_InheritString(p_this, "lastfm-password"); /* username or password have not been setup */ if (EMPTY_STR(psz_username) || EMPTY_STR(psz_password)) { free(psz_username); free(psz_password); return VLC_ENOVAR; } time(×tamp); /* generates a md5 hash of the password */ InitMD5(&p_struct_md5); AddMD5(&p_struct_md5, (uint8_t*) psz_password, strlen(psz_password)); EndMD5(&p_struct_md5); free(psz_password); char *psz_password_md5 = psz_md5_hash(&p_struct_md5); if (!psz_password_md5) { free(psz_username); return VLC_ENOMEM; } snprintf(psz_timestamp, sizeof(psz_timestamp), "%"PRIu64, (uint64_t)timestamp); /* generates a md5 hash of : * - md5 hash of the password, plus * - timestamp in clear text */ InitMD5(&p_struct_md5); AddMD5(&p_struct_md5, (uint8_t*) psz_password_md5, 32); AddMD5(&p_struct_md5, (uint8_t*) psz_timestamp, strlen(psz_timestamp)); EndMD5(&p_struct_md5); free(psz_password_md5); char *psz_auth_token = psz_md5_hash(&p_struct_md5); if (!psz_auth_token) { free(psz_username); return VLC_ENOMEM; } psz_scrobbler_url = var_InheritString(p_this, "scrobbler-url"); if (!psz_scrobbler_url) { free(psz_auth_token); free(psz_username); return VLC_ENOMEM; } i_ret = asprintf(&psz_handshake_url, "http://%s/?hs=true&p=1.2&c="CLIENT_NAME"&v="CLIENT_VERSION"&u=%s&t=%s&a=%s" , psz_scrobbler_url, psz_username, psz_timestamp, psz_auth_token); free(psz_auth_token); free(psz_scrobbler_url); free(psz_username); if (i_ret == -1) return VLC_ENOMEM; /* send the http handshake request */ p_stream = vlc_stream_NewURL(p_intf, psz_handshake_url); free(psz_handshake_url); if (!p_stream) return VLC_EGENERIC; /* read answer */ i_ret = vlc_stream_Read(p_stream, p_buffer, sizeof(p_buffer) - 1); if (i_ret <= 0) { vlc_stream_Delete(p_stream); return VLC_EGENERIC; } p_buffer[i_ret] = '\0'; vlc_stream_Delete(p_stream); p_buffer_pos = strstr((char*) p_buffer, "FAILED "); if (p_buffer_pos) { /* handshake request failed, sorry */ msg_Err(p_this, "last.fm handshake failed: %s", p_buffer_pos + 7); return VLC_EGENERIC; } if (strstr((char*) p_buffer, "BADAUTH")) { /* authentication failed, bad username/password combination */ vlc_dialog_display_error(p_this, _("last.fm: Authentication failed"), "%s", _("last.fm username or password is incorrect. " "Please verify your settings and relaunch VLC.")); return VLC_AUDIOSCROBBLER_EFATAL; } if (strstr((char*) p_buffer, "BANNED")) { /* oops, our version of vlc has been banned by last.fm servers */ msg_Err(p_intf, "This version of VLC has been banned by last.fm. " "You should upgrade VLC, or disable the last.fm plugin."); return VLC_AUDIOSCROBBLER_EFATAL; } if (strstr((char*) p_buffer, "BADTIME")) { /* The system clock isn't good */ msg_Err(p_intf, "last.fm handshake failed because your clock is too " "much shifted. Please correct it, and relaunch VLC."); return VLC_AUDIOSCROBBLER_EFATAL; } p_buffer_pos = strstr((char*) p_buffer, "OK"); if (!p_buffer_pos) goto proto; p_buffer_pos = strstr(p_buffer_pos, "\n"); if (!p_buffer_pos || strlen(p_buffer_pos) < 33) goto proto; p_buffer_pos++; /* we skip the '\n' */ /* save the session ID */ memcpy(p_sys->psz_auth_token, p_buffer_pos, 32); p_sys->psz_auth_token[32] = '\0'; p_buffer_pos = strstr(p_buffer_pos, "http://"); if (!p_buffer_pos || strlen(p_buffer_pos) == 7) goto proto; /* We need to read the nowplaying url */ psz_url = strndup(p_buffer_pos, strcspn(p_buffer_pos, "\n")); if (!psz_url) goto oom; vlc_UrlParse(&p_sys->p_nowp_url, psz_url); free(psz_url); if (p_sys->p_nowp_url.psz_host == NULL || p_sys->p_nowp_url.i_port == 0) { vlc_UrlClean(&p_sys->p_nowp_url); goto proto; } p_buffer_pos += strcspn(p_buffer_pos, "\n"); p_buffer_pos = strstr(p_buffer_pos, "http://"); if (!p_buffer_pos || strlen(p_buffer_pos) == 7) goto proto; /* We need to read the submission url */ psz_url = strndup(p_buffer_pos, strcspn(p_buffer_pos, "\n")); if (!psz_url) goto oom; /* parse the submission url */ vlc_UrlParse(&p_sys->p_submit_url, psz_url); free(psz_url); if (p_sys->p_submit_url.psz_host == NULL || p_sys->p_submit_url.i_port == 0) { vlc_UrlClean(&p_sys->p_nowp_url); vlc_UrlClean(&p_sys->p_submit_url); goto proto; } return VLC_SUCCESS; oom: return VLC_ENOMEM; proto: msg_Err(p_intf, "Handshake: can't recognize server protocol"); return VLC_EGENERIC; }
static int MimeDemux( demux_t *p_demux ) { demux_sys_t *p_sys = p_demux->p_sys; int i_size, i; bool b_match = CheckMimeHeader( p_demux, &i_size ); if( i_size > 0 ) { if( vlc_stream_Read( p_demux->s, NULL, i_size ) != i_size ) return 0; } else if( i_size < 0 ) { return 0; } else { // No MIME header, assume OK b_match = true; } if( !Peek( p_demux, true ) ) { msg_Warn( p_demux, "cannot peek data" ); return 0; } i = 0; i_size = strlen( p_sys->psz_separator ) + 2; if( p_sys->i_data_peeked < i_size ) { msg_Warn( p_demux, "data shortage" ); return 0; } for( ;; ) { while( !( p_sys->p_peek[i] == '-' && p_sys->p_peek[i+1] == '-' ) ) { i++; i_size++; if( i_size >= p_sys->i_data_peeked ) { msg_Dbg( p_demux, "MIME boundary not found in %d bytes of " "data", p_sys->i_data_peeked ); if( !Peek( p_demux, false ) ) { msg_Warn( p_demux, "no more data is available at the " "moment" ); return 0; } } } /* Handle old and new style of separators */ if (!strncmp(p_sys->psz_separator, (char *)(p_sys->p_peek + i + 2), strlen( p_sys->psz_separator )) || ((strlen(p_sys->psz_separator) > 4) && !strncmp(p_sys->psz_separator, "--", 2) && !strncmp(p_sys->psz_separator, (char *)(p_sys->p_peek + i), strlen( p_sys->psz_separator)))) { break; } i++; i_size++; } if( !b_match ) { msg_Err( p_demux, "discard non-JPEG part" ); vlc_stream_Read( p_demux->s, NULL, i ); return 0; } return SendBlock( p_demux, i ); }