/***************************************************************************** * ffmpeg_InitCodec: setup codec extra initialization data for ffmpeg *****************************************************************************/ static void ffmpeg_InitCodec( decoder_t *p_dec ) { decoder_sys_t *p_sys = p_dec->p_sys; int i_size = p_dec->fmt_in.i_extra; if( !i_size ) return; if( p_sys->i_codec_id == CODEC_ID_SVQ3 ) { uint8_t *p; p_sys->p_context->extradata_size = i_size + 12; p = p_sys->p_context->extradata = malloc( p_sys->p_context->extradata_size ); if( !p ) return; memcpy( &p[0], "SVQ3", 4 ); memset( &p[4], 0, 8 ); memcpy( &p[12], p_dec->fmt_in.p_extra, i_size ); /* Now remove all atoms before the SMI one */ if( p_sys->p_context->extradata_size > 0x5a && strncmp( (char*)&p[0x56], "SMI ", 4 ) ) { uint8_t *psz = &p[0x52]; while( psz < &p[p_sys->p_context->extradata_size - 8] ) { int i_size = GetDWBE( psz ); if( i_size <= 1 ) { /* FIXME handle 1 as long size */ break; } if( !strncmp( (char*)&psz[4], "SMI ", 4 ) ) { memmove( &p[0x52], psz, &p[p_sys->p_context->extradata_size] - psz ); break; } psz += i_size; } } } else { p_sys->p_context->extradata_size = i_size; p_sys->p_context->extradata = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE ); if( p_sys->p_context->extradata ) { memcpy( p_sys->p_context->extradata, p_dec->fmt_in.p_extra, i_size ); memset( &((uint8_t*)p_sys->p_context->extradata)[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE ); } } }
static void U32BDecode( void *outp, const uint8_t *in, unsigned samples ) { uint32_t *out = outp; for( size_t i = 0; i < samples; i++ ) { *(out++) = GetDWBE( in ) - 0x80000000; in += 4; } }
static bool IsLbm(stream_t *s) { const uint8_t *header; if (stream_Peek(s, &header, 12) < 12) return false; if (memcmp(&header[0], "FORM", 4) || GetDWBE(&header[4]) <= 4 || (memcmp(&header[8], "ILBM", 4) && memcmp(&header[8], "PBM ", 4))) return false; return true; }
/* Attempt to find dirac picture number in an encapsulation unit */ static int ReadDiracPictureNumber( uint32_t *p_picnum, block_t *p_block ) { uint32_t u_pos = 4; /* protect against falling off the edge */ while( u_pos + 13 < p_block->i_buffer ) { /* find the picture startcode */ if( p_block->p_buffer[u_pos] & 0x08 ) { *p_picnum = GetDWBE( p_block->p_buffer + u_pos + 9 ); return 1; } /* skip to the next dirac data unit */ uint32_t u_npo = GetDWBE( p_block->p_buffer + u_pos + 1 ); assert( u_npo <= UINT32_MAX - u_pos ); if( u_npo == 0 ) u_npo = 13; u_pos += u_npo; } return 0; }
static void S32IDecode( void *outp, const uint8_t *in, unsigned samples ) { int32_t *out = outp; for( size_t i = 0; i < samples; i++ ) { #ifdef WORDS_BIGENDIAN *(out++) = GetDWLE( in ); #else *(out++) = GetDWBE( in ); #endif in += 4; } }
static void F32IDecode( void *outp, const uint8_t *in, unsigned samples ) { float *out = outp; for( size_t i = 0; i < samples; i++ ) { union { float f; uint32_t u; } s; #ifdef WORDS_BIGENDIAN s.u = GetDWLE( in ); #else s.u = GetDWBE( in ); #endif *(out++) = s.f; in += 4; } }
/*** * Packet (Data Unit) inspection, learns parameters from sequence * headers, sets up flags, drops unwanted data units, sets * encapsulation unit termination policy */ static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t *p_eu ) { decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = *pp_block; uint8_t u_parse_code = p_block->p_buffer[4]; if( dirac_isEOS( u_parse_code ) ) { if( p_sys->b_seen_eos ) { /* remove duplicate EOS packets */ block_Release( p_block ); *pp_block = NULL; return DIRAC_DU_IN_EU; } /* p_block is an EOS packet */ p_eu->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE; /* for the moment, let this end an encapsulation unit */ /* seeing an eos packet requires a flush of the packetizer * this is detected by the caller of this function */ p_sys->b_seen_seq_hdr = false; p_sys->b_seen_eos = true; return DIRAC_DU_ENDS_EU; #if 0 /* let anything down streem know too */ /* Actually, this is a bad idea: - It sets the discontinuity for every dirac EOS packet which doesnt imply a time discontinuity. - When the synchronizer detects a real discontinuity, it should copy the flags through. p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY; */ #endif } p_sys->b_seen_eos = false; if( dirac_isPicture( u_parse_code ) ) { /* timestamps apply to pictures only */ p_eu->i_dts = p_sys->i_eu_dts; p_eu->i_pts = p_sys->i_eu_pts; p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID; if( !p_sys->b_seen_seq_hdr ) { /* can't timestamp in this case, discard later * so that the timestamps aren't lost */ p_eu->i_flags |= DIRAC_DISCARD; } /* p_block is a picture -- it ends the 'encapsulation unit' */ if( dirac_numRefs( u_parse_code ) ) { /* if this picture is not an I frame, ensure that the * random access point flags are not set */ p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I; } dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block ); if( p_dbe && p_block->i_buffer > 13+4 ) { /* record the picture number to save the time gen functions * from having to inspect the data for it */ p_dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 ); } return DIRAC_DU_ENDS_EU; } if( dirac_isSeqHdr( u_parse_code ) ) { if( !dirac_UnpackSeqHdr( &p_sys->seq_hdr, p_block ) ) { /* couldn't parse the sequence header, just ignore it */ return DIRAC_DU_IN_EU; } p_sys->b_seen_seq_hdr = true; /* a sequence header followed by an I frame is a random * access point; assume that this is the case */ p_eu->i_flags |= BLOCK_FLAG_TYPE_I; es_format_t *p_es = &p_dec->fmt_out; p_es->video.i_width = p_sys->seq_hdr.u_width; p_es->video.i_height = p_sys->seq_hdr.u_height; vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 ); /* when field coding, dts needs to be incremented in terms of field periods */ unsigned u_pics_per_sec = p_sys->seq_hdr.u_fps_num; if( p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING ) { u_pics_per_sec *= 2; } date_Change( &p_sys->dts, u_pics_per_sec, p_sys->seq_hdr.u_fps_den ); /* TODO: set p_sys->reorder_buf.u_size_max */ p_sys->i_pts_offset = p_sys->reorder_buf.u_size_max * 1000000 * p_es->video.i_frame_rate_base / p_es->video.i_frame_rate + 1; /* stash a copy of the seqhdr * - required for ogg muxing * - useful for error checking * - it isn't allowed to change until an eos */ free( p_es->p_extra ); p_es->p_extra = calloc( 1, p_block->i_buffer + 13 ); if( !p_es->p_extra ) { p_es->i_extra = 0; return DIRAC_DU_IN_EU; } p_es->i_extra = p_block->i_buffer; memcpy( p_es->p_extra, p_block->p_buffer, p_block->i_buffer ); /* append EOS as per Ogg guidelines */ p_block = dirac_EmitEOS( p_dec, p_block->i_buffer ); if( p_block ) { memcpy( (uint8_t*)p_es->p_extra + p_es->i_extra, p_block->p_buffer, 13 ); p_es->i_extra += 13; } return DIRAC_DU_IN_EU; } /* doesn't end an encapsulation unit */ return DIRAC_DU_IN_EU; }
/***************************************************************************** * OpenVideo: *****************************************************************************/ static int OpenVideo( decoder_t *p_dec ) { #ifndef WIN32 decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; long i_result; ComponentDescription desc; Component prev; ComponentResult cres; ImageSubCodecDecompressCapabilities icap; /* for ImageCodecInitialize() */ CodecInfo cinfo; /* for ImageCodecGetCodecInfo() */ ImageDescription *id; char fcc[4]; int i_vide = p_dec->fmt_in.i_extra; uint8_t *p_vide = p_dec->fmt_in.p_extra; p_dec->p_sys = p_sys; p_dec->pf_decode_video = DecodeVideo; p_sys->i_late = 0; if( i_vide <= 0 ) { msg_Err( p_dec, "missing extra info" ); free( p_sys ); return VLC_EGENERIC; } if( p_dec->fmt_in.i_original_fourcc ) memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 ); else memcpy( fcc, &p_dec->fmt_in.i_codec, 4 ); msg_Dbg( p_dec, "quicktime_video %4.4s %dx%d", fcc, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); /* get lock, avoid segfault */ vlc_mutex_lock( &qt_mutex ); #ifdef __APPLE__ EnterMovies(); #endif if( QTVideoInit( p_dec ) ) { msg_Err( p_dec, "cannot initialize QT"); goto exit_error; } #ifndef __APPLE__ if( ( i_result = p_sys->InitializeQTML( 6 + 16 ) ) ) { msg_Dbg( p_dec, "error on InitializeQTML = %d", (int)i_result ); goto exit_error; } #endif /* init ComponentDescription */ memset( &desc, 0, sizeof( ComponentDescription ) ); desc.componentType = FCC( 'i', 'm', 'd', 'c' ); desc.componentSubType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); desc.componentManufacturer = 0; desc.componentFlags = 0; desc.componentFlagsMask = 0; if( !( prev = p_sys->FindNextComponent( NULL, &desc ) ) ) { msg_Err( p_dec, "cannot find requested component" ); goto exit_error; } msg_Dbg( p_dec, "component id=0x%p", prev ); p_sys->ci = p_sys->OpenComponent( prev ); msg_Dbg( p_dec, "component instance p=0x%p", p_sys->ci ); memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) ); cres = p_sys->ImageCodecInitialize( p_sys->ci, &icap ); msg_Dbg( p_dec, "ImageCodecInitialize->0x%X size=%d (%d)", (int)cres, (int)icap.recordSize, (int)icap.decompressRecordSize); memset( &cinfo, 0, sizeof( CodecInfo ) ); cres = p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo ); msg_Dbg( p_dec, "Flags: compr: 0x%x decomp: 0x%x format: 0x%x", (unsigned int)cinfo.compressFlags, (unsigned int)cinfo.decompressFlags, (unsigned int)cinfo.formatFlags ); msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s", ((unsigned char*)&cinfo.typeName)[0], ((unsigned char*)&cinfo.typeName)+1 ); /* make a yuy2 gworld */ p_sys->OutBufferRect.top = 0; p_sys->OutBufferRect.left = 0; p_sys->OutBufferRect.right = p_dec->fmt_in.video.i_width; p_sys->OutBufferRect.bottom = p_dec->fmt_in.video.i_height; /* codec data FIXME use codec not SVQ3 */ msg_Dbg( p_dec, "vide = %d", i_vide ); id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) ); if( !id ) goto exit_error; id->idSize = sizeof( ImageDescription ) + ( i_vide - 70 ); id->cType = FCC( fcc[0], fcc[1], fcc[2], fcc[3] ); id->version = GetWBE ( p_vide + 0 ); id->revisionLevel = GetWBE ( p_vide + 2 ); id->vendor = GetDWBE( p_vide + 4 ); id->temporalQuality = GetDWBE( p_vide + 8 ); id->spatialQuality = GetDWBE( p_vide + 12 ); id->width = GetWBE ( p_vide + 16 ); id->height = GetWBE ( p_vide + 18 ); id->hRes = GetDWBE( p_vide + 20 ); id->vRes = GetDWBE( p_vide + 24 ); id->dataSize = GetDWBE( p_vide + 28 ); id->frameCount = GetWBE ( p_vide + 32 ); memcpy( &id->name, p_vide + 34, 32 ); id->depth = GetWBE ( p_vide + 66 ); id->clutID = GetWBE ( p_vide + 68 ); if( i_vide > 70 ) { memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 ); } msg_Dbg( p_dec, "idSize=%d ver=%d rev=%d vendor=%d tempQ=%d " "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d depth=%d frameCount=%d clutID=%d", (int)id->idSize, id->version, id->revisionLevel, (int)id->vendor, (int)id->temporalQuality, (int)id->spatialQuality, (int)id->width, (int)id->height, (int)id->hRes, (int)id->vRes, (int)id->dataSize, id->depth, id->frameCount, id->clutID ); p_sys->framedescHandle = (ImageDescriptionHandle) NewHandleClear( id->idSize ); memcpy( *p_sys->framedescHandle, id, id->idSize ); if( p_dec->fmt_in.video.i_width != 0 && p_dec->fmt_in.video.i_height != 0) p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 ); if( !p_sys->plane ) goto exit_error; i_result = p_sys->QTNewGWorldFromPtr( &p_sys->OutBufferGWorld, /*pixel format of new GWorld==YUY2 */ kYUVSPixelFormat, /* we should benchmark if yvu9 is * faster for svq3, too */ &p_sys->OutBufferRect, 0, 0, 0, p_sys->plane, p_dec->fmt_in.video.i_width * 2 ); msg_Dbg( p_dec, "NewGWorldFromPtr returned:%ld", 65536 - ( i_result&0xffff ) ); memset( &p_sys->decpar, 0, sizeof( CodecDecompressParams ) ); p_sys->decpar.imageDescription = p_sys->framedescHandle; p_sys->decpar.startLine = 0; p_sys->decpar.stopLine = ( **p_sys->framedescHandle ).height; p_sys->decpar.frameNumber = 1; p_sys->decpar.matrixFlags = 0; p_sys->decpar.matrixType = 0; p_sys->decpar.matrix = 0; p_sys->decpar.capabilities = &p_sys->codeccap; p_sys->decpar.accuracy = codecNormalQuality; p_sys->decpar.srcRect = p_sys->OutBufferRect; p_sys->decpar.transferMode = srcCopy; p_sys->decpar.dstPixMap = **p_sys->GetGWorldPixMap( p_sys->OutBufferGWorld );/*destPixmap; */ cres = p_sys->ImageCodecPreDecompress( p_sys->ci, &p_sys->decpar ); msg_Dbg( p_dec, "quicktime_video: ImageCodecPreDecompress cres=0x%X", (int)cres ); es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_CODEC_YUYV); p_dec->fmt_out.video.i_width = p_dec->fmt_in.video.i_width; p_dec->fmt_out.video.i_height= p_dec->fmt_in.video.i_height; p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_in.video.i_width / p_dec->fmt_in.video.i_height; vlc_mutex_unlock( &qt_mutex ); return VLC_SUCCESS; exit_error: #ifdef LOADER Restore_LDT_Keeper( p_sys->ldt_fs ); #endif vlc_mutex_unlock( &qt_mutex ); #else VLC_UNUSED( p_dec ); #endif /* !WIN32 */ return VLC_EGENERIC; }
static int BdHeader( decoder_sys_t *p_sys, unsigned *pi_rate, unsigned *pi_channels, unsigned *pi_channels_padding, unsigned *pi_original_channels, unsigned *pi_bits, const uint8_t *p_header ) { const uint32_t h = GetDWBE( p_header ); const uint32_t *pi_channels_in = NULL; switch( ( h & 0xf000) >> 12 ) { case 1: *pi_channels = 1; *pi_original_channels = AOUT_CHAN_CENTER; break; case 3: *pi_channels = 2; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; break; case 4: *pi_channels = 3; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER; pi_channels_in = pi_3channels_in; break; case 5: *pi_channels = 3; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER; break; case 6: *pi_channels = 4; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER; break; case 7: *pi_channels = 4; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; pi_channels_in = pi_4channels_in; break; case 8: *pi_channels = 5; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; pi_channels_in = pi_5channels_in; break; case 9: *pi_channels = 6; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; pi_channels_in = pi_6channels_in; break; case 10: *pi_channels = 7; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT; pi_channels_in = pi_7channels_in; break; case 11: *pi_channels = 8; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE; pi_channels_in = pi_8channels_in; break; default: return -1; } *pi_channels_padding = *pi_channels & 1; switch( (h >> 6) & 0x03 ) { case 1: *pi_bits = 16; break; case 2: /* 20 bits but samples are stored on 24 bits */ case 3: /* 24 bits */ *pi_bits = 24; break; default: return -1; } switch( (h >> 8) & 0x0f ) { case 1: *pi_rate = 48000; break; case 4: *pi_rate = 96000; break; case 5: *pi_rate = 192000; break; default: return -1; } if( pi_channels_in ) { p_sys->i_chans_to_reorder = aout_CheckChannelReorder( pi_channels_in, NULL, *pi_original_channels, p_sys->pi_chan_table ); } return 0; }
static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit ) { vlc_object_t *p_obj = p_session->p_obj; msg_Dbg( p_obj, "NITCallBack" ); msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d", p_nit->i_network_id, p_nit->i_version, p_nit->b_current_next ); /* */ if( p_session->p_nit && p_session->p_nit->b_current_next ) { dvbpsi_DeleteNIT( p_session->p_nit ); p_session->p_nit = NULL; } if( p_session->p_nit ) { dvbpsi_DeleteNIT( p_nit ); return; } /* */ p_session->p_nit = p_nit; dvbpsi_descriptor_t *p_dsc; for( p_dsc = p_nit->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next ) { if( p_dsc->i_tag == 0x40 ) { msg_Dbg( p_obj, " * network name descriptor" ); char str1[257]; memcpy( str1, p_dsc->p_data, p_dsc->i_length ); str1[p_dsc->i_length] = '\0'; msg_Dbg( p_obj, " * name %s", str1 ); } else if( p_dsc->i_tag == 0x4a ) { msg_Dbg( p_obj, " * linkage descriptor" ); uint16_t i_ts_id = GetWBE( &p_dsc->p_data[0] ); uint16_t i_on_id = GetWBE( &p_dsc->p_data[2] ); uint16_t i_service_id = GetWBE( &p_dsc->p_data[4] ); int i_linkage_type = p_dsc->p_data[6]; msg_Dbg( p_obj, " * ts_id %d", i_ts_id ); msg_Dbg( p_obj, " * on_id %d", i_on_id ); msg_Dbg( p_obj, " * service_id %d", i_service_id ); msg_Dbg( p_obj, " * linkage_type %d", i_linkage_type ); } else { msg_Dbg( p_obj, " * dsc 0x%x", p_dsc->i_tag ); } } dvbpsi_nit_ts_t *p_ts; for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next ) { msg_Dbg( p_obj, " * ts ts_id=0x%x original_id=0x%x", p_ts->i_ts_id, p_ts->i_orig_network_id ); uint32_t i_private_data_id = 0; dvbpsi_descriptor_t *p_dsc; for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next ) { if( p_dsc->i_tag == 0x41 ) { msg_Dbg( p_obj, " * service list descriptor" ); for( int i = 0; i < p_dsc->i_length/3; i++ ) { uint16_t i_service_id = GetWBE( &p_dsc->p_data[3*i+0] ); uint8_t i_service_type = p_dsc->p_data[3*i+2]; msg_Dbg( p_obj, " * service_id=%d type=%d", i_service_id, i_service_type ); } } else if( p_dsc->i_tag == 0x5a ) { dvbpsi_terr_deliv_sys_dr_t *p_t = dvbpsi_DecodeTerrDelivSysDr( p_dsc ); msg_Dbg( p_obj, " * terrestrial delivery system" ); msg_Dbg( p_obj, " * centre_frequency 0x%x", p_t->i_centre_frequency ); msg_Dbg( p_obj, " * bandwidth %d", 8 - p_t->i_bandwidth ); msg_Dbg( p_obj, " * constellation %d", p_t->i_constellation ); msg_Dbg( p_obj, " * hierarchy %d", p_t->i_hierarchy_information ); msg_Dbg( p_obj, " * code_rate hp %d lp %d", p_t->i_code_rate_hp_stream, p_t->i_code_rate_lp_stream ); msg_Dbg( p_obj, " * guard_interval %d", p_t->i_guard_interval ); msg_Dbg( p_obj, " * transmission_mode %d", p_t->i_transmission_mode ); msg_Dbg( p_obj, " * other_frequency_flag %d", p_t->i_other_frequency_flag ); } else if( p_dsc->i_tag == 0x5f ) { msg_Dbg( p_obj, " * private data specifier descriptor" ); i_private_data_id = GetDWBE( &p_dsc->p_data[0] ); msg_Dbg( p_obj, " * value 0x%8.8x", i_private_data_id ); } else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 ) { msg_Dbg( p_obj, " * logical channel descriptor (EICTA)" ); for( int i = 0; i < p_dsc->i_length/4; i++ ) { uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] ); int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff; msg_Dbg( p_obj, " * service_id=%d channel_number=%d", i_service_id, i_channel_number ); } } else { msg_Warn( p_obj, " * dsc 0x%x", p_dsc->i_tag ); } } } }
/***************************************************************************** * Decode: *****************************************************************************/ static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ) { block_t *p_block; subpicture_t *p_spu = NULL; if( ( pp_block == NULL ) || ( *pp_block == NULL ) ) return NULL; p_block = *pp_block; *pp_block = NULL; if( ( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) || p_block->i_buffer < sizeof(uint16_t) ) { block_Release( p_block ); return NULL; } uint8_t *p_buf = p_block->p_buffer; /* Read our raw string and create the styled segment for HTML */ uint16_t i_psz_length = GetWBE( p_buf ); char *psz_subtitle = malloc( i_psz_length + 1 ); if ( !psz_subtitle ) return NULL; memcpy( psz_subtitle, p_block->p_buffer + sizeof(uint16_t), i_psz_length ); psz_subtitle[ i_psz_length ] = '\0'; p_buf += i_psz_length + sizeof(uint16_t); for( uint16_t i=0; i < i_psz_length; i++ ) if ( psz_subtitle[i] == '\r' ) psz_subtitle[i] = '\n'; segment_t *p_segment = calloc( 1, sizeof(segment_t) ); if ( !p_segment ) { free( psz_subtitle ); return NULL; } p_segment->psz_string = strdup( psz_subtitle ); p_segment->i_size = strlen( psz_subtitle ); if ( p_dec->fmt_in.subs.p_style ) { p_segment->styles.i_color = p_dec->fmt_in.subs.p_style->i_font_color; p_segment->styles.i_color |= p_dec->fmt_in.subs.p_style->i_font_alpha << 24; if ( p_dec->fmt_in.subs.p_style->i_style_flags ) p_segment->styles.i_flags = p_dec->fmt_in.subs.p_style->i_style_flags; p_segment->styles.i_fontsize = p_dec->fmt_in.subs.p_style->i_font_size; } if ( !p_segment->psz_string ) { SegmentFree( p_segment ); free( psz_subtitle ); return NULL; } /* Create the subpicture unit */ p_spu = decoder_NewSubpictureText( p_dec ); if( !p_spu ) { free( psz_subtitle ); SegmentFree( p_segment ); return NULL; } subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; /* Parse our styles */ while( (size_t)(p_buf - p_block->p_buffer) + 8 < p_block->i_buffer ) { uint32_t i_atomsize = GetDWBE( p_buf ); vlc_fourcc_t i_atomtype = VLC_FOURCC(p_buf[4],p_buf[5],p_buf[6],p_buf[7]); p_buf += 8; switch( i_atomtype ) { case VLC_FOURCC('s','t','y','l'): { if ( (size_t)(p_buf - p_block->p_buffer) < 14 ) break; uint16_t i_nbrecords = GetWBE(p_buf); uint16_t i_cur_record = 0; p_buf += 2; while( i_cur_record++ < i_nbrecords ) { if ( (size_t)(p_buf - p_block->p_buffer) < 12 ) break; uint16_t i_start = __MIN( GetWBE(p_buf), i_psz_length - 1 ); uint16_t i_end = __MIN( GetWBE(p_buf + 2), i_psz_length - 1 ); segment_style_t style; style.i_flags = ConvertFlags( p_buf[6] ); style.i_fontsize = p_buf[7]; style.i_color = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB style.i_color |= (GetDWBE(p_buf+8) & 0xFF) << 24; ApplySegmentStyle( &p_segment, i_start, i_end, &style ); if ( i_nbrecords == 1 ) { if ( p_buf[6] ) { p_spu_sys->style_flags.i_value = ConvertFlags( p_buf[6] ); p_spu_sys->style_flags.b_set = true; } p_spu_sys->i_font_height_abs_to_src = p_buf[7]; p_spu_sys->font_color.i_value = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB p_spu_sys->font_color.i_value |= (GetDWBE(p_buf+8) & 0xFF) << 24; p_spu_sys->font_color.b_set = true; } p_buf += 12; } } break; case VLC_FOURCC('d','r','p','o'): if ( (size_t)(p_buf - p_block->p_buffer) < 4 ) break; p_spu_sys->i_drop_shadow = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) ); break; case VLC_FOURCC('d','r','p','t'): if ( (size_t)(p_buf - p_block->p_buffer) < 2 ) break; p_spu_sys->i_drop_shadow_alpha = GetWBE(p_buf); break; default: break; } p_buf += i_atomsize; } p_spu->i_start = p_block->i_pts; p_spu->i_stop = p_block->i_pts + p_block->i_length; p_spu->b_ephemer = (p_block->i_length == 0); p_spu->b_absolute = false; p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM; p_spu_sys->text = psz_subtitle; p_spu_sys->p_htmlsegments = p_segment; block_Release( p_block ); return p_spu; }
/***************************************************************************** * 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; }
void scan_session_Clean( scan_t *p_scan, scan_session_t *p_session ) { const int i_service_start = p_scan->i_service; dvbpsi_pat_t *p_pat = p_session->p_pat; dvbpsi_sdt_t *p_sdt = p_session->p_sdt; #ifdef DVBPSI_USE_NIT dvbpsi_nit_t *p_nit = p_session->p_nit; #endif if( p_pat ) { /* Parse PAT */ dvbpsi_pat_program_t *p_program; for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next ) { if( p_program->i_number == 0 ) /* NIT */ continue; scan_service_t *s = scan_service_New( p_program->i_number, &p_session->cfg ); TAB_APPEND( p_scan->i_service, p_scan->pp_service, s ); } } /* Parse SDT */ if( p_pat && p_sdt ) { dvbpsi_sdt_service_t *p_srv; for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next ) { scan_service_t *s = ScanFindService( p_scan, i_service_start, p_srv->i_service_id ); dvbpsi_descriptor_t *p_dr; if( s ) s->b_crypted = p_srv->b_free_ca; for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next ) { if( p_dr->i_tag == 0x48 ) { dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr ); if( s ) { if( !s->psz_name ) s->psz_name = dvbsi_to_utf8( pD->i_service_name, pD->i_service_name_length ); if( s->type == SERVICE_UNKNOWN ) { switch( pD->i_service_type ) { case 0x01: s->type = SERVICE_DIGITAL_TELEVISION; break; case 0x02: s->type = SERVICE_DIGITAL_RADIO; break; case 0x16: s->type = SERVICE_DIGITAL_TELEVISION_AC_SD; break; case 0x19: s->type = SERVICE_DIGITAL_TELEVISION_AC_HD; break; } } } } } } } #ifdef DVBPSI_USE_NIT /* Parse NIT */ if( p_pat && p_nit ) { dvbpsi_nit_ts_t *p_ts; for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next ) { uint32_t i_private_data_id = 0; dvbpsi_descriptor_t *p_dsc; if( p_ts->i_orig_network_id != p_nit->i_network_id || p_ts->i_ts_id != p_pat->i_ts_id ) continue; for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next ) { if( p_dsc->i_tag == 0x5f ) { i_private_data_id = GetDWBE( &p_dsc->p_data[0] ); } else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 ) { for( int i = 0; i < p_dsc->i_length/4; i++ ) { uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] ); int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff; scan_service_t *s = ScanFindService( p_scan, i_service_start, i_service_id ); if( s && s->i_channel < 0 ) s->i_channel = i_channel_number; } } } } } #endif /* */ for( int i = i_service_start; i < p_scan->i_service; i++ ) { scan_service_t *p_srv = p_scan->pp_service[i]; p_srv->i_snr = p_session->i_snr; if( p_sdt ) p_srv->i_sdt_version = p_sdt->i_version; #ifdef DVBPSI_USE_NIT if( p_nit ) { p_srv->i_network_id = p_nit->i_network_id; p_srv->i_nit_version = p_nit->i_version; } #endif } /* */ if( p_session->pat ) dvbpsi_DetachPAT( p_session->pat ); if( p_session->p_pat ) dvbpsi_DeletePAT( p_session->p_pat ); if( p_session->sdt ) dvbpsi_DetachDemux( p_session->sdt ); if( p_session->p_sdt ) dvbpsi_DeleteSDT( p_session->p_sdt ); #ifdef DVBPSI_USE_NIT if( p_session->nit ) dvbpsi_DetachDemux( p_session->nit ); if( p_session->p_nit ) dvbpsi_DeleteNIT( p_session->p_nit ); #endif }
int OpenDemux( vlc_object_t* p_this ) { demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; const uint8_t *p_peek; ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 ); if( unlikely( i_peek <= 32 ) ) return VLC_EGENERIC; const char *psz_xml = (const char *) p_peek; size_t i_xml = i_peek; /* Try to probe without xml module/loading the full document */ char *psz_alloc = NULL; switch( GetQWBE(p_peek) ) { /* See RFC 3023 Part 4 */ case UINT64_C(0xFFFE3C003F007800): /* UTF16 BOM<? */ case UINT64_C(0xFFFE3C003F007400): /* UTF16 BOM<t */ case UINT64_C(0xFEFF003C003F0078): /* UTF16 BOM<? */ case UINT64_C(0xFEFF003C003F0074): /* UTF16 BOM<t */ psz_alloc = FromCharset( "UTF-16", p_peek, i_peek ); break; case UINT64_C(0x3C003F0078006D00): /* UTF16-LE <?xm */ case UINT64_C(0x3C003F0074007400): /* UTF16-LE <tt */ psz_alloc = FromCharset( "UTF-16LE", p_peek, i_peek ); break; case UINT64_C(0x003C003F0078006D): /* UTF16-BE <?xm */ case UINT64_C(0x003C003F00740074): /* UTF16-BE <tt */ psz_alloc = FromCharset( "UTF-16BE", p_peek, i_peek ); break; case UINT64_C(0xEFBBBF3C3F786D6C): /* UTF8 BOM<?xml */ case UINT64_C(0x3C3F786D6C207665): /* UTF8 <?xml ve */ case UINT64_C(0xEFBBBF3C74742078): /* UTF8 BOM<tt x*/ break; default: if(GetDWBE(p_peek) != UINT32_C(0x3C747420)) /* tt node without xml document marker */ return VLC_EGENERIC; } if( psz_alloc ) { psz_xml = psz_alloc; i_xml = strlen( psz_alloc ); } /* Simplified probing. Valid TTML must have a namespace declaration */ const char *psz_tt = strnstr( psz_xml, "tt ", i_xml ); if( !psz_tt || psz_tt == psz_xml || (psz_tt[-1] != ':' && psz_tt[-1] != '<') ) { free( psz_alloc ); return VLC_EGENERIC; } else { const char * const rgsz[] = { "=\"http://www.w3.org/ns/ttml\"", "=\"http://www.w3.org/2004/11/ttaf1\"", "=\"http://www.w3.org/2006/04/ttaf1\"", "=\"http://www.w3.org/2006/10/ttaf1\"", }; const char *psz_ns = NULL; for( size_t i=0; i<ARRAY_SIZE(rgsz) && !psz_ns; i++ ) { psz_ns = strnstr( psz_xml, rgsz[i], i_xml - (psz_tt - psz_xml) ); } free( psz_alloc ); if( !psz_ns ) return VLC_EGENERIC; } p_demux->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) ); if( unlikely( p_sys == NULL ) ) return VLC_ENOMEM; p_sys->b_first_time = true; p_sys->temporal_extent.i_type = TT_TIMINGS_PARALLEL; tt_time_Init( &p_sys->temporal_extent.begin ); tt_time_Init( &p_sys->temporal_extent.end ); tt_time_Init( &p_sys->temporal_extent.dur ); p_sys->temporal_extent.begin.base = 0; p_sys->p_xml = xml_Create( p_demux ); if( !p_sys->p_xml ) goto error; p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s ); if( !p_sys->p_reader ) goto error; #ifndef TTML_DEMUX_DEBUG p_sys->p_reader->obj.flags |= OBJECT_FLAGS_QUIET; #endif if( ReadTTML( p_demux ) != VLC_SUCCESS ) goto error; tt_timings_Resolve( (tt_basenode_t *) p_sys->p_rootnode, &p_sys->temporal_extent, &p_sys->times.p_array, &p_sys->times.i_count ); #ifdef TTML_DEMUX_DEBUG { struct vlc_memstream stream; if( vlc_memstream_open( &stream ) ) goto error; tt_time_t t; tt_time_Init( &t ); tt_node_ToText( &stream, (tt_basenode_t*)p_sys->p_rootnode, &t /* invalid */ ); vlc_memstream_putc( &stream, '\0' ); if( vlc_memstream_close( &stream ) == VLC_SUCCESS ) { msg_Dbg( p_demux, "%s", stream.ptr ); free( stream.ptr ); } } #endif p_demux->pf_demux = Demux; p_demux->pf_control = Control; es_format_t fmt; es_format_Init( &fmt, SPU_ES, VLC_CODEC_TTML ); p_sys->p_es = es_out_Add( p_demux->out, &fmt ); if( !p_sys->p_es ) goto error; es_format_Clean( &fmt ); return VLC_SUCCESS; error: CloseDemux( p_demux ); return VLC_EGENERIC; }
input_attachment_t* ParseFlacPicture( const uint8_t *p_data, int i_data, int i_attachments, int *i_cover_score, int *i_cover_idx ) { /* TODO: Merge with ID3v2 copy in modules/meta_engine/taglib.cpp. */ static const char pi_cover_score[] = { 0, /* Other */ 5, /* 32x32 PNG image that should be used as the file icon */ 4, /* File icon of a different size or format. */ 20, /* Front cover image of the album. */ 19, /* Back cover image of the album. */ 13, /* Inside leaflet page of the album. */ 18, /* Image from the album itself. */ 17, /* Picture of the lead artist or soloist. */ 16, /* Picture of the artist or performer. */ 14, /* Picture of the conductor. */ 15, /* Picture of the band or orchestra. */ 9, /* Picture of the composer. */ 8, /* Picture of the lyricist or text writer. */ 7, /* Picture of the recording location or studio. */ 10, /* Picture of the artists during recording. */ 11, /* Picture of the artists during performance. */ 6, /* Picture from a movie or video related to the track. */ 1, /* Picture of a large, coloured fish. */ 12, /* Illustration related to the track. */ 3, /* Logo of the band or performer. */ 2 /* Logo of the publisher (record company). */ }; int i_len; int i_type; char *psz_mime = NULL; char psz_name[128]; char *psz_description = NULL; input_attachment_t *p_attachment = NULL; if( i_data < 4 + 3*4 ) return NULL; #define RM(x) do { i_data -= (x); p_data += (x); } while(0) i_type = GetDWBE( p_data ); RM(4); i_len = GetDWBE( p_data ); RM(4); if( i_len < 0 || i_data < i_len + 4 ) goto error; psz_mime = strndup( (const char*)p_data, i_len ); RM(i_len); i_len = GetDWBE( p_data ); RM(4); if( i_len < 0 || i_data < i_len + 4*4 + 4) goto error; psz_description = strndup( (const char*)p_data, i_len ); RM(i_len); EnsureUTF8( psz_description ); RM(4*4); i_len = GetDWBE( p_data ); RM(4); if( i_len < 0 || i_len > i_data ) goto error; /* printf( "Picture type=%d mime=%s description='%s' file length=%d\n", i_type, psz_mime, psz_description, i_len ); */ snprintf( psz_name, sizeof(psz_name), "picture%d", i_attachments ); if( !strcasecmp( psz_mime, "image/jpeg" ) ) strcat( psz_name, ".jpg" ); else if( !strcasecmp( psz_mime, "image/png" ) ) strcat( psz_name, ".png" ); p_attachment = vlc_input_attachment_New( psz_name, psz_mime, psz_description, p_data, i_data ); if( i_type >= 0 && (unsigned int)i_type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) && *i_cover_score < pi_cover_score[i_type] ) { *i_cover_idx = i_attachments; *i_cover_score = pi_cover_score[i_type]; } error: free( psz_mime ); free( psz_description ); return p_attachment; }
/**************************************************************************** * Encode: the whole thing **************************************************************************** * This function spits out encapsulation units. ****************************************************************************/ static block_t *Encode( encoder_t *p_enc, picture_t *p_pic ) { encoder_sys_t *p_sys = p_enc->p_sys; block_t *p_block, *p_output_chain = NULL; int i_plane, i_line, i_width, i_src_stride; uint8_t *p_dst; if( !p_pic ) return NULL; /* we only know if the sequence is interlaced when the first * picture arrives, so final setup is done here */ /* XXX todo, detect change of interlace */ p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first; p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive; if( p_sys->b_auto_field_coding ) p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive; if( !p_sys->p_dirac ) { date_t date; /* Initialise the encoder with the encoder context */ p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 ); if( !p_sys->p_dirac ) { msg_Err( p_enc, "Failed to initialize dirac encoder" ); return NULL; } date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base ); #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2) int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac ); i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1; date_Increment( &date, i_delayinpics ); #else date_Increment( &date, 1 ); #endif p_sys->i_pts_offset = date_Get( &date ); /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced * for each frame input. Calculate time between fields for offsetting * the second field later. */ if( 1 == p_sys->ctx.enc_params.picture_coding_mode ) { date_Set( &date, 0 ); date_Increment( &date, 1 ); p_sys->i_field_time = date_Get( &date ) / 2; } } /* Copy input picture into encoder input buffer (stride by stride) */ /* Would be lovely to just pass the picture in, but there is noway for the * library to free it */ p_dst = p_sys->p_buffer_in; for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { uint8_t *p_src = p_pic->p[i_plane].p_pixels; i_width = p_pic->p[i_plane].i_visible_pitch; i_src_stride = p_pic->p[i_plane].i_pitch; for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ ) { vlc_memcpy( p_dst, p_src, i_width ); p_dst += i_width; p_src += i_src_stride; } } /* Load one frame of data into encoder */ if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in, p_sys->i_buffer_in ) < 0 ) { msg_Dbg( p_enc, "dirac_encoder_load() error" ); return NULL; } /* store pts in a lookaside buffer, so that the same pts may * be used for the picture in coded order */ StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date ); p_sys->i_input_picnum++; /* store dts in a queue, so that they appear in order in * coded order */ p_block = block_New( p_enc, 1 ); if( !p_block ) return NULL; p_block->i_dts = p_pic->date - p_sys->i_pts_offset; block_FifoPut( p_sys->p_dts_fifo, p_block ); p_block = NULL; /* for field coding mode, insert an extra value into both the * pts lookaside buffer and dts queue, offset to correspond * to a one field delay. */ if( 1 == p_sys->ctx.enc_params.picture_coding_mode ) { StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time ); p_sys->i_input_picnum++; p_block = block_New( p_enc, 1 ); if( !p_block ) return NULL; p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time; block_FifoPut( p_sys->p_dts_fifo, p_block ); p_block = NULL; } dirac_encoder_state_t state; /* Retrieve encoded frames from encoder */ do { p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out; p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out; state = dirac_encoder_output( p_sys->p_dirac ); switch( state ) { case ENC_STATE_AVAIL: { uint32_t pic_num; /* extract data from encoder temporary buffer. */ p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size ); if( !p_block ) return NULL; memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer, p_sys->p_dirac->enc_buf.size ); /* if some flags were set for a previous block, prevent * them from getting lost */ if( p_sys->p_chain ) p_block->i_flags |= p_sys->p_chain->i_flags; /* store all extracted blocks in a chain and gather up when an * entire encapsulation unit is avaliable (ends with a picture) */ block_ChainAppend( &p_sys->p_chain, p_block ); /* Presence of a Sequence header indicates a seek point */ if( 0 == p_block->p_buffer[4] ) { p_block->i_flags |= BLOCK_FLAG_TYPE_I; if( !p_enc->fmt_out.p_extra ) { const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 }; uint32_t len = GetDWBE( p_block->p_buffer + 5 ); /* if it hasn't been done so far, stash a copy of the * sequence header for muxers such as ogg */ /* The OggDirac spec advises that a Dirac EOS DataUnit * is appended to the sequence header to allow guard * against poor streaming servers */ /* XXX, should this be done using the packetizer ? */ p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) ); if( !p_enc->fmt_out.p_extra ) return NULL; memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len); memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) ); SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len ); p_enc->fmt_out.i_extra = len + sizeof(eos); } } if( ReadDiracPictureNumber( &pic_num, p_block ) ) { /* Finding a picture terminates an ecapsulation unit, gather * all data and output; use the next dts value queued up * and find correct pts in the tlb */ p_block = block_FifoGet( p_sys->p_dts_fifo ); p_sys->p_chain->i_dts = p_block->i_dts; p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num ); block_Release( p_block ); block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) ); p_sys->p_chain = NULL; } else { p_block = NULL; } break; } case ENC_STATE_BUFFER: break; case ENC_STATE_INVALID: default: break; } } while( state == ENC_STATE_AVAIL ); return p_output_chain; }
/***************************************************************************** * Open: check file and initializes structures *****************************************************************************/ static int Open (vlc_object_t * p_this) { demux_t *p_demux = (demux_t *)p_this; stream_t *stream = p_demux->s; demux_sys_t *p_sys; const uint8_t *peek; unsigned tracks, ppqn; bool multitrack; /* (Try to) parse the SMF header */ /* Header chunk always has 6 bytes payload */ if (stream_Peek (stream, &peek, 14) < 14) return VLC_EGENERIC; /* Skip RIFF MIDI header if present */ if (!memcmp (peek, "RIFF", 4) && !memcmp (peek + 8, "RMID", 4)) { uint32_t riff_len = GetDWLE (peek + 4); msg_Dbg (p_this, "detected RIFF MIDI file (%u bytes)", (unsigned)riff_len); if ((stream_Read (stream, NULL, 12) < 12)) return VLC_EGENERIC; /* Look for the RIFF data chunk */ for (;;) { char chnk_hdr[8]; uint32_t chnk_len; if ((riff_len < 8) || (stream_Read (stream, chnk_hdr, 8) < 8)) return VLC_EGENERIC; riff_len -= 8; chnk_len = GetDWLE (chnk_hdr + 4); if (riff_len < chnk_len) return VLC_EGENERIC; riff_len -= chnk_len; if (!memcmp (chnk_hdr, "data", 4)) break; /* found! */ if (stream_Read (stream, NULL, chnk_len) < (ssize_t)chnk_len) return VLC_EGENERIC; } /* Read real SMF header. Assume RIFF data chunk length is proper. */ if (stream_Peek (stream, &peek, 14) < 14) return VLC_EGENERIC; } if (memcmp (peek, "MThd\x00\x00\x00\x06", 8)) return VLC_EGENERIC; peek += 8; /* First word: SMF type */ switch (GetWBE (peek)) { case 0: multitrack = false; break; case 1: multitrack = true; break; default: /* We don't implement SMF2 (as do many) */ msg_Err (p_this, "unsupported SMF file type %u", GetWBE (peek)); return VLC_EGENERIC; } peek += 2; /* Second word: number of tracks */ tracks = GetWBE (peek); peek += 2; if (!multitrack && (tracks != 1)) { msg_Err (p_this, "invalid SMF type 0 file"); return VLC_EGENERIC; } msg_Dbg (p_this, "detected Standard MIDI File (type %u) with %u track(s)", multitrack, tracks); /* Third/last word: timing */ ppqn = GetWBE (peek); if (ppqn & 0x8000) { /* FIXME */ msg_Err (p_this, "SMPTE timestamps not implemented"); return VLC_EGENERIC; } else { msg_Dbg (p_this, " %u pulses per quarter note", ppqn); } p_sys = malloc (sizeof (*p_sys) + (sizeof (mtrk_t) * tracks)); if (p_sys == NULL) return VLC_ENOMEM; /* We've had a valid SMF header - now skip it*/ if (stream_Read (stream, NULL, 14) < 14) goto error; p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys; /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */ date_Init (&p_sys->pts, ppqn * 2, 1); date_Set (&p_sys->pts, 0); p_sys->pulse = 0; p_sys->ppqn = ppqn; p_sys->trackc = tracks; /* Prefetch track offsets */ for (unsigned i = 0; i < tracks; i++) { uint8_t head[8]; if (i > 0) { /* Seeking screws streaming up, but there is no way around this, * as SMF1 tracks are performed simultaneously. * Not a big deal as SMF1 are usually only a few kbytes anyway. */ if (stream_Seek (stream, p_sys->trackv[i-1].end)) { msg_Err (p_this, "cannot build SMF index (corrupted file?)"); goto error; } } for (;;) { if (stream_Read (stream, head, 8) < 8) { /* FIXME: don't give up if we have at least one valid track */ msg_Err (p_this, "incomplete SMF chunk, file is corrupted"); goto error; } if (memcmp (head, "MTrk", 4) == 0) break; msg_Dbg (p_this, "skipping unknown SMF chunk"); stream_Read (stream, NULL, GetDWBE (head + 4)); } p_sys->trackv[i].offset = stream_Tell (stream); p_sys->trackv[i].end = p_sys->trackv[i].offset + GetDWBE (head + 4); p_sys->trackv[i].next = 0; ReadDeltaTime (stream, p_sys->trackv + i); p_sys->trackv[i].running_event = 0xF6; /* Why 0xF6 (Tuning Calibration)? * Because it has zero bytes of data, so the parser will detect the * error if the first event uses running status. */ } es_format_t fmt; es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MIDI); fmt.audio.i_channels = 2; fmt.audio.i_rate = 44100; /* dummy value */ p_sys->es = es_out_Add (p_demux->out, &fmt); return VLC_SUCCESS; error: free (p_sys); return VLC_EGENERIC; }
/***************************************************************************** * InitVideo: initialize the video decoder ***************************************************************************** * the ffmpeg codec will be opened, some memory allocated. The vout is not yet * opened (done after the first decoded frame). *****************************************************************************/ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, char *psz_namecodec ) { decoder_sys_t *p_sys; vlc_value_t lockval; vlc_value_t val; var_Get( p_dec->p_libvlc, "avcodec", &lockval ); /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } p_dec->p_sys->p_context = p_context; p_dec->p_sys->p_codec = p_codec; p_dec->p_sys->i_codec_id = i_codec_id; p_dec->p_sys->psz_namecodec = psz_namecodec; p_sys->p_ff_pic = avcodec_alloc_frame(); /* ***** Fill p_context with init values ***** */ /* FIXME: remove when ffmpeg deals properly with avc1 */ if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','v','c','1') ) /* End FIXME */ p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_codec ); p_sys->p_context->width = p_dec->fmt_in.video.i_width; p_sys->p_context->height = p_dec->fmt_in.video.i_height; p_sys->p_context->bits_per_sample = p_dec->fmt_in.video.i_bits_per_pixel; /* ***** Get configuration of ffmpeg plugin ***** */ p_sys->p_context->workaround_bugs = config_GetInt( p_dec, "ffmpeg-workaround-bugs" ); p_sys->p_context->error_resilience = config_GetInt( p_dec, "ffmpeg-error-resilience" ); var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "grayscale", &val ); if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY; var_Create( p_dec, "ffmpeg-vismv", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-vismv", &val ); #if LIBAVCODEC_BUILD >= 4698 if( val.i_int ) p_sys->p_context->debug_mv = val.i_int; #endif var_Create( p_dec, "ffmpeg-lowres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-lowres", &val ); #if LIBAVCODEC_BUILD >= 4723 if( val.i_int > 0 && val.i_int <= 2 ) p_sys->p_context->lowres = val.i_int; #endif /* ***** ffmpeg frame skipping ***** */ var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-hurry-up", &val ); p_sys->b_hurry_up = val.b_bool; /* ***** ffmpeg direct rendering ***** */ p_sys->b_direct_rendering = 0; var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "ffmpeg-dr", &val ); if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) && ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) && /* Apparently direct rendering doesn't work with YUV422P */ p_sys->p_context->pix_fmt != PIX_FMT_YUV422P && /* H264 uses too many reference frames */ p_sys->i_codec_id != CODEC_ID_H264 && !(p_sys->p_context->width % 16) && !(p_sys->p_context->height % 16) && #if LIBAVCODEC_BUILD >= 4698 !p_sys->p_context->debug_mv ) #else 1 ) #endif { /* Some codecs set pix_fmt only after the 1st frame has been decoded, * so we need to do another check in ffmpeg_GetFrameBuf() */ p_sys->b_direct_rendering = 1; } #ifdef LIBAVCODEC_PP p_sys->p_pp = NULL; p_sys->b_pp = p_sys->b_pp_async = p_sys->b_pp_init = VLC_FALSE; p_sys->p_pp = E_(OpenPostproc)( p_dec, &p_sys->b_pp_async ); #endif /* ffmpeg doesn't properly release old pictures when frames are skipped */ //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = 0; if( p_sys->b_direct_rendering ) { msg_Dbg( p_dec, "using direct rendering" ); p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE; } /* Always use our get_buffer wrapper so we can calculate the * PTS correctly */ p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf; p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf; p_sys->p_context->opaque = p_dec; /* ***** init this codec with special data ***** */ if( p_dec->fmt_in.i_extra ) { int i_size = p_dec->fmt_in.i_extra; if( p_sys->i_codec_id == CODEC_ID_SVQ3 ) { uint8_t *p; p_sys->p_context->extradata_size = i_size + 12; p = p_sys->p_context->extradata = malloc( p_sys->p_context->extradata_size ); memcpy( &p[0], "SVQ3", 4 ); memset( &p[4], 0, 8 ); memcpy( &p[12], p_dec->fmt_in.p_extra, i_size ); /* Now remove all atoms before the SMI one */ if( p_sys->p_context->extradata_size > 0x5a && strncmp( &p[0x56], "SMI ", 4 ) ) { uint8_t *psz = &p[0x52]; while( psz < &p[p_sys->p_context->extradata_size - 8] ) { int i_size = GetDWBE( psz ); if( i_size <= 1 ) { /* FIXME handle 1 as long size */ break; } if( !strncmp( &psz[4], "SMI ", 4 ) ) { memmove( &p[0x52], psz, &p[p_sys->p_context->extradata_size] - psz ); break; } psz += i_size; } } } else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '0' ) || p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '3' ) || p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '2', '0' ) ) { if( p_dec->fmt_in.i_extra == 8 ) { p_sys->p_context->extradata_size = 8; p_sys->p_context->extradata = malloc( 8 ); memcpy( p_sys->p_context->extradata, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); p_sys->p_context->sub_id= ((uint32_t*)p_dec->fmt_in.p_extra)[1]; msg_Warn( p_dec, "using extra data for RV codec sub_id=%08x", p_sys->p_context->sub_id ); } } /* FIXME: remove when ffmpeg deals properly with avc1 */ else if( p_dec->fmt_in.i_codec == VLC_FOURCC('a','v','c','1') ) { ; } /* End FIXME */ else { p_sys->p_context->extradata_size = i_size; p_sys->p_context->extradata = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE ); memcpy( p_sys->p_context->extradata, p_dec->fmt_in.p_extra, i_size ); memset( &((uint8_t*)p_sys->p_context->extradata)[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE ); } } /* ***** misc init ***** */ p_sys->input_pts = p_sys->input_dts = 0; p_sys->i_pts = 0; p_sys->b_has_b_frames = VLC_FALSE; p_sys->b_first_frame = VLC_TRUE; p_sys->i_late_frames = 0; p_sys->i_buffer = 0; p_sys->i_buffer_orig = 1; p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer_orig ); /* Set output properties */ p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt ); /* Setup palette */ #if LIBAVCODEC_BUILD >= 4688 if( p_dec->fmt_in.video.p_palette ) p_sys->p_context->palctrl = (AVPaletteControl *)p_dec->fmt_in.video.p_palette; else p_sys->p_context->palctrl = &palette_control; #endif /* ***** Open the codec ***** */ vlc_mutex_lock( lockval.p_address ); if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 ) { vlc_mutex_unlock( lockval.p_address ); msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); free( p_sys ); return VLC_EGENERIC; } vlc_mutex_unlock( lockval.p_address ); msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec ); return VLC_SUCCESS; }
static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig ) { /* First update information based on i_objectTypeIndication */ switch( p_decconfig->i_objectProfileIndication ) { case( 0x20 ): /* MPEG4 VIDEO */ p_track->fmt.i_codec = VLC_CODEC_MP4V; break; case( 0x21 ): /* H.264 */ p_track->fmt.i_codec = VLC_CODEC_H264; break; case( 0x40): p_track->fmt.i_codec = VLC_CODEC_MP4A; if( p_decconfig->i_decoder_specific_info_len >= 2 && p_decconfig->p_decoder_specific_info[0] == 0xF8 && (p_decconfig->p_decoder_specific_info[1]&0xE0) == 0x80 ) { p_track->fmt.i_codec = VLC_CODEC_ALS; } break; case( 0x60): case( 0x61): case( 0x62): case( 0x63): case( 0x64): case( 0x65): /* MPEG2 video */ p_track->fmt.i_codec = VLC_CODEC_MPGV; break; /* Theses are MPEG2-AAC */ case( 0x66): /* main profile */ case( 0x67): /* Low complexity profile */ case( 0x68): /* Scaleable Sampling rate profile */ p_track->fmt.i_codec = VLC_CODEC_MP4A; break; /* True MPEG 2 audio */ case( 0x69): p_track->fmt.i_codec = VLC_CODEC_MPGA; break; case( 0x6a): /* MPEG1 video */ p_track->fmt.i_codec = VLC_CODEC_MPGV; break; case( 0x6b): /* MPEG1 audio */ p_track->fmt.i_codec = VLC_CODEC_MPGA; break; case( 0x6c ): /* jpeg */ p_track->fmt.i_codec = VLC_CODEC_JPEG; break; case( 0x6d ): /* png */ p_track->fmt.i_codec = VLC_CODEC_PNG; break; case( 0x6e ): /* jpeg2000 */ p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' ); break; case( 0xa3 ): /* vc1 */ p_track->fmt.i_codec = VLC_CODEC_VC1; break; case( 0xa4 ): p_track->fmt.i_codec = VLC_CODEC_DIRAC; break; case( 0xa5 ): p_track->fmt.i_codec = VLC_CODEC_A52; break; case( 0xa6 ): p_track->fmt.i_codec = VLC_CODEC_EAC3; break; case( 0xa9 ): /* dts */ case( 0xaa ): /* DTS-HD HRA */ case( 0xab ): /* DTS-HD Master Audio */ p_track->fmt.i_codec = VLC_CODEC_DTS; break; case( 0xDD ): p_track->fmt.i_codec = VLC_CODEC_VORBIS; break; /* Private ID */ case( 0xe0 ): /* NeroDigital: dvd subs */ if( p_track->fmt.i_cat == SPU_ES ) { p_track->fmt.i_codec = VLC_CODEC_SPU; if( p_track->i_width > 0 ) p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width; if( p_track->i_height > 0 ) p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height; break; } case( 0xe1 ): /* QCelp for 3gp */ if( p_track->fmt.i_cat == AUDIO_ES ) { p_track->fmt.i_codec = VLC_CODEC_QCELP; } break; /* Fallback */ default: /* Unknown entry, but don't touch i_fourcc */ msg_Warn( p_demux, "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])", p_decconfig->i_objectProfileIndication, p_track->i_track_ID ); break; } p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len; if( p_track->fmt.i_extra > 0 ) { p_track->fmt.p_extra = malloc( p_track->fmt.i_extra ); memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info, p_track->fmt.i_extra ); } if( p_track->fmt.i_codec == VLC_CODEC_SPU && p_track->fmt.i_extra >= 16 * 4 ) { for( int i = 0; i < 16; i++ ) { p_track->fmt.subs.spu.palette[1 + i] = GetDWBE((char*)p_track->fmt.p_extra + i * 4); } p_track->fmt.subs.spu.palette[0] = 0xBeef; } }
/***************************************************************************** * Decode: *****************************************************************************/ static int Decode( decoder_t *p_dec, block_t *p_block ) { subpicture_t *p_spu = NULL; if( p_block == NULL ) /* No Drain */ return VLCDEC_SUCCESS; if( ( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) ) || p_block->i_buffer < sizeof(uint16_t) ) { block_Release( p_block ); return VLCDEC_SUCCESS; } uint8_t *p_buf = p_block->p_buffer; /* Read our raw string and create the styled segment for HTML */ uint16_t i_psz_bytelength = GetWBE( p_buf ); const uint8_t *p_pszstart = p_block->p_buffer + sizeof(uint16_t); char *psz_subtitle; if ( i_psz_bytelength > 2 && ( !memcmp( p_pszstart, "\xFE\xFF", 2 ) || !memcmp( p_pszstart, "\xFF\xFE", 2 ) ) ) { psz_subtitle = FromCharset( "UTF-16", p_pszstart, i_psz_bytelength ); if ( !psz_subtitle ) return VLCDEC_SUCCESS; } else { psz_subtitle = malloc( i_psz_bytelength + 1 ); if ( !psz_subtitle ) return VLCDEC_SUCCESS; memcpy( psz_subtitle, p_pszstart, i_psz_bytelength ); psz_subtitle[ i_psz_bytelength ] = '\0'; } p_buf += i_psz_bytelength + sizeof(uint16_t); for( uint16_t i=0; i < i_psz_bytelength; i++ ) if ( psz_subtitle[i] == '\r' ) psz_subtitle[i] = '\n'; tx3g_segment_t *p_segment3g = tx3g_segment_New( psz_subtitle ); p_segment3g->i_size = str8len( psz_subtitle ); if ( p_dec->fmt_in.subs.p_style ) p_segment3g->s->style = text_style_Duplicate( p_dec->fmt_in.subs.p_style ); free( psz_subtitle ); if ( !p_segment3g->s->psz_text ) { text_segment_Delete( p_segment3g->s ); free( p_segment3g ); return VLCDEC_SUCCESS; } /* Create the subpicture unit */ p_spu = decoder_NewSubpictureText( p_dec ); if( !p_spu ) { text_segment_Delete( p_segment3g->s ); free( p_segment3g ); return VLCDEC_SUCCESS; } subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys; /* Parse our styles */ while( (size_t)(p_buf - p_block->p_buffer) + 8 < p_block->i_buffer ) { uint32_t i_atomsize = GetDWBE( p_buf ); vlc_fourcc_t i_atomtype = VLC_FOURCC(p_buf[4],p_buf[5],p_buf[6],p_buf[7]); p_buf += 8; switch( i_atomtype ) { case VLC_FOURCC('s','t','y','l'): { if ( (size_t)(p_buf - p_block->p_buffer) < 14 ) break; uint16_t i_nbrecords = GetWBE(p_buf); uint16_t i_cur_record = 0; p_buf += 2; while( i_cur_record++ < i_nbrecords ) { if ( (size_t)(p_buf - p_block->p_buffer) < 12 ) break; uint16_t i_start = __MIN( GetWBE(p_buf), i_psz_bytelength - 1 ); uint16_t i_end = __MIN( GetWBE(p_buf + 2), i_psz_bytelength - 1 ); text_style_t style; memset( &style, 0, sizeof(text_style_t) ); style.i_style_flags = ConvertFlags( p_buf[6] ); style.i_font_size = p_buf[7]; style.i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> RGB style.i_font_alpha = GetDWBE(p_buf+8) & 0xFF; style.i_features = STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA; ApplySegmentStyle( &p_segment3g, i_start, i_end, &style ); if ( i_nbrecords == 1 ) { if ( p_buf[6] ) { if( (p_spu_sys->p_default_style->i_style_flags = ConvertFlags( p_buf[6] )) ) p_spu_sys->p_default_style->i_features |= STYLE_HAS_FLAGS; } p_spu_sys->p_default_style->i_font_size = p_buf[7]; p_spu_sys->p_default_style->i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB p_spu_sys->p_default_style->i_font_alpha = (GetDWBE(p_buf+8) & 0xFF) << 24; p_spu_sys->p_default_style->i_features |= (STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA); } p_buf += 12; } } break; case VLC_FOURCC('d','r','p','o'): if ( (size_t)(p_buf - p_block->p_buffer) < 4 ) break; p_spu_sys->p_default_style->i_shadow_width = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) ); break; case VLC_FOURCC('d','r','p','t'): if ( (size_t)(p_buf - p_block->p_buffer) < 2 ) break; p_spu_sys->p_default_style->i_shadow_alpha = GetWBE(p_buf); p_spu_sys->p_default_style->i_features |= STYLE_HAS_SHADOW_ALPHA; break; default: break; } p_buf += i_atomsize; } p_spu->i_start = p_block->i_pts; p_spu->i_stop = p_block->i_pts + p_block->i_length; p_spu->b_ephemer = (p_block->i_length == 0); p_spu->b_absolute = false; p_spu_sys->region.inner_align = SUBPICTURE_ALIGN_BOTTOM; FontSizeConvert( p_dec->fmt_in.subs.p_style, p_spu_sys->p_default_style ); /* Unwrap */ text_segment_t *p_text_segments = p_segment3g->s; text_segment_t *p_cur = p_text_segments; while( p_segment3g ) { FontSizeConvert( p_dec->fmt_in.subs.p_style, p_segment3g->s->style ); tx3g_segment_t * p_old = p_segment3g; p_segment3g = p_segment3g->p_next3g; free( p_old ); if( p_segment3g ) p_cur->p_next = p_segment3g->s; p_cur = p_cur->p_next; } p_spu_sys->region.p_segments = p_text_segments; block_Release( p_block ); decoder_QueueSub( p_dec, p_spu ); return VLCDEC_SUCCESS; }
void xiph_decode (demux_t *demux, void *data, block_t *block) { rtp_xiph_t *self = (rtp_xiph_t *)data; // sunqueen modify if (!data || block->i_buffer < 4) goto drop; /* 32-bits RTP header (§2.2) */ uint32_t ident = GetDWBE (block->p_buffer); block->i_buffer -= 4; block->p_buffer += 4; unsigned fragtype = (ident >> 6) & 3; unsigned datatype = (ident >> 4) & 3; unsigned pkts = (ident) & 15; ident >>= 8; /* RTP defragmentation */ if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY)) { /* Screwed! discontinuity within a fragmented packet */ msg_Warn (demux, self->vorbis ? "discontinuity in fragmented Vorbis packet" : "discontinuity in fragmented Theora packet"); block_Release (self->block); self->block = NULL; } if (fragtype <= 1) { if (self->block) /* Invalid first fragment */ { block_Release (self->block); self->block = NULL; } } else { if (!self->block) goto drop; /* Invalid non-first fragment */ } if (fragtype > 0) { /* Fragment */ if (pkts > 0 || block->i_buffer < 2) goto drop; size_t fraglen = GetWBE (block->p_buffer); if (block->i_buffer < (fraglen + 2)) goto drop; /* Invalid payload length */ block->i_buffer = fraglen; if (fragtype == 1)/* Keep first fragment */ { block->i_buffer += 2; self->block = block; } else { /* Append non-first fragment */ size_t len = self->block->i_buffer; self->block = block_Realloc (self->block, 0, len + fraglen); if (!self->block) { block_Release (block); return; } memcpy (self->block->p_buffer + len, block->p_buffer + 2, fraglen); block_Release (block); } if (fragtype < 3) return; /* Non-last fragment */ /* Last fragment reached, process it */ block = self->block; self->block = NULL; SetWBE (block->p_buffer, block->i_buffer - 2); pkts = 1; } /* RTP payload packets processing */ while (pkts > 0) { if (block->i_buffer < 2) goto drop; size_t len = GetWBE (block->p_buffer); block->i_buffer -= 2; block->p_buffer += 2; if (block->i_buffer < len) goto drop; switch (datatype) { case 0: /* Raw payload */ { if (self->ident != ident) { msg_Warn (demux, self->vorbis ? "ignoring raw Vorbis payload without configuration" : "ignoring raw Theora payload without configuration"); break; } block_t *raw = block_Alloc (len); memcpy (raw->p_buffer, block->p_buffer, len); raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */ codec_decode (demux, self->id, raw); break; } case 1: /* Packed configuration frame (§3.1.1) */ { if (self->ident == ident) break; /* Ignore config retransmission */ void *extv; ssize_t extc = xiph_header (&extv, block->p_buffer, len); if (extc < 0) break; es_format_t fmt; es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES, self->vorbis ? VLC_CODEC_VORBIS : VLC_CODEC_THEORA); fmt.p_extra = extv; fmt.i_extra = extc; codec_destroy (demux, self->id); msg_Dbg (demux, self->vorbis ? "Vorbis packed configuration received (%06"PRIx32")" : "Theora packed configuration received (%06"PRIx32")", ident); self->ident = ident; self->id = (es_out_id_t *)codec_init (demux, &fmt); // sunqueen modify break; } } block->i_buffer -= len; block->p_buffer += len; pkts--; } drop: block_Release (block); }
/*** * Encapsulation (packetization) suitable for all muxing standards * maps [DataUnit] -> EncapsulationUnit */ static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block ) { decoder_sys_t *p_sys = p_dec->p_sys; assert(p_block->i_buffer >= 13 && 0x42424344 == GetDWBE( p_block->p_buffer )); if( p_sys->i_eu_pts <= VLC_TS_INVALID && p_sys->i_eu_dts <= VLC_TS_INVALID ) { /* earliest block with pts/dts gets to set the pts/dts for the dated * encapsulation unit as a whole */ /* NB, the 'earliest block' criteria is aribtary */ if( p_block->i_pts > VLC_TS_INVALID || p_block->i_dts > VLC_TS_INVALID ) { p_sys->i_eu_pts = p_block->i_pts; p_sys->i_eu_dts = p_block->i_dts; } } /* inpectdataunit also updates flags for the EU. * - if this is the first block in the EU, then it hasn't been added * to the chain yet (so, p_block will become the front of the chain * - otherwise, use the flags of the chain (first block) */ block_t *p_eu = p_sys->p_eu ? p_sys->p_eu : p_block; int i_block = dirac_InspectDataUnit( p_dec, &p_block, p_eu); if( !p_block ) { /* block has been discarded during inspection */ /* becareful, don't discard anything that is dated, * as this needs to go into the timegen loop. set * the DIRAC_DISCARD block flag, and it'll be dropped * at output time */ return NULL; } block_ChainLastAppend( &p_sys->pp_eu_last, p_block ); dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block ); #ifdef SANITIZE_PREV_PARSE_OFFSET /* fixup prev_parse_offset to point to the last data unit * to arrive */ if( p_dbe ) { SetDWBE( p_block->p_buffer + 9, p_sys->u_eu_last_npo ); p_sys->u_eu_last_npo = p_dbe->u_last_next_offset; } #endif if( i_block != DIRAC_DU_ENDS_EU ) { /* encapsulation unit not ended */ return NULL; } /* gather up encapsulation unit, reassociating the final * private state with the gathered block */ block_t *p_eu_last = (block_t*) p_sys->pp_eu_last - offsetof( block_t, p_next ); p_dbe = dirac_RemoveBlockEncap( p_eu_last ); uint8_t u_parse_code = p_block->p_buffer[4]; /* gather up the encapsulation unit */ p_block = block_ChainGather( p_sys->p_eu ); assert( p_block ); /* block_ChainGather doesn't define when it frees chain */ p_block->i_flags |= DIRAC_NON_DATED; if( p_dbe ) { dirac_AddBlockEncap( &p_block, p_dbe ); if( dirac_isPicture( u_parse_code ) ) p_block->i_flags &= ~DIRAC_NON_DATED; } p_sys->p_eu = NULL; p_sys->pp_eu_last = &p_sys->p_eu; return p_block; }
static int BdHeader( unsigned *pi_rate, unsigned *pi_channels, unsigned *pi_original_channels, unsigned *pi_bits, const uint8_t *p_header ) { const uint32_t h = GetDWBE( p_header ); switch( ( h & 0xf000) >> 12 ) { case 1: *pi_channels = 1; *pi_original_channels = AOUT_CHAN_CENTER; break; case 3: *pi_channels = 2; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; break; case 4: *pi_channels = 3; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER; break; case 5: *pi_channels = 3; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER; break; case 6: *pi_channels = 4; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARCENTER; break; case 7: *pi_channels = 4; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; break; case 8: *pi_channels = 5; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; break; case 9: *pi_channels = 6; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; break; case 10: *pi_channels = 7; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT; break; case 11: *pi_channels = 8; *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT | AOUT_CHAN_LFE; break; default: return -1; } switch( (h >> 6) & 0x03 ) { case 1: *pi_bits = 16; break; case 2: /* 20 bits but samples are stored on 24 bits */ case 3: /* 24 bits */ *pi_bits = 24; break; default: return -1; } switch( (h >> 8) & 0x0f ) { case 1: *pi_rate = 48000; break; case 4: *pi_rate = 96000; break; case 5: *pi_rate = 192000; break; default: return -1; } return 0; }
/***************************************************************************** * 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; int i_samples, i_modulo; if( stream_Peek( p_demux->s , &p_peek, 4 ) < 4 ) return VLC_EGENERIC; if( memcmp( p_peek, ".snd", 4 ) ) return VLC_EGENERIC; /* skip signature */ stream_Read( p_demux->s, NULL, 4 ); /* cannot fail */ /* read header */ if( 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; } DEMUX_INIT_COMMON(); p_sys = p_demux->p_sys; p_sys->i_time = 0; p_sys->i_header_size = GetDWBE( &hdr[0] ); /* skip extra header data */ if( p_sys->i_header_size > 24 ) { stream_Read( p_demux->s, NULL, p_sys->i_header_size - 24 ); } /* 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_FOURCC( 't','w','o','s' ); 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_FOURCC( 't','w','o','s' ); 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_FOURCC( 't','w','o','s' ); 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_FOURCC( 't','w','o','s' ); 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, "unknow 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 ) { p_sys->i_frame_size = 0; p_sys->i_frame_length = 0; msg_Err( p_demux, "unsupported codec/type (Please report it)" ); free( p_sys ); return VLC_EGENERIC; } if( p_sys->fmt.audio.i_rate == 0 ) { msg_Err( p_demux, "invalid samplerate: 0" ); free( p_sys ); return VLC_EGENERIC; } /* add the es */ p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt ); /* calculate 50ms frame size/time */ 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 ) { if( ( i_modulo = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign ) != 0 ) { p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - i_modulo; } } p_sys->i_frame_length = (mtime_t)1000000 * (mtime_t)i_samples / (mtime_t)p_sys->fmt.audio.i_rate; return VLC_SUCCESS; }