/***************************************************************************** * Open *****************************************************************************/ static int Open(vlc_object_t *p_this) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if (p_dec->fmt_in.i_codec != VLC_CODEC_HEVC) return VLC_EGENERIC; p_dec->p_sys = p_sys = calloc(1, sizeof(decoder_sys_t)); if (!p_dec->p_sys) return VLC_ENOMEM; p_sys->pp_frame_last = &p_sys->p_frame; packetizer_Init(&p_dec->p_sys->packetizer, p_hevc_startcode, sizeof(p_hevc_startcode), startcode_FindAnnexB, p_hevc_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec); /* Copy properties */ es_format_Copy(&p_dec->fmt_out, &p_dec->fmt_in); p_dec->fmt_out.b_packetized = true; /* Set callbacks */ const uint8_t *p_extra = p_dec->fmt_in.p_extra; const size_t i_extra = p_dec->fmt_in.i_extra; /* Check if we have hvcC as extradata */ if(hevc_ishvcC(p_extra, i_extra)) { p_dec->pf_packetize = PacketizeHVC1; /* Clear hvcC/HVC1 extra, to be replaced with AnnexB */ free(p_dec->fmt_out.p_extra); p_dec->fmt_out.i_extra = 0; size_t i_new_extra = 0; p_dec->fmt_out.p_extra = hevc_hvcC_to_AnnexB_NAL(p_extra, i_extra, &i_new_extra, &p_sys->i_nal_length_size); if(p_dec->fmt_out.p_extra) p_dec->fmt_out.i_extra = i_new_extra; } else { p_dec->pf_packetize = PacketizeAnnexB; } p_dec->pf_flush = PacketizeFlush; if(p_dec->fmt_out.i_extra) { /* Feed with AnnexB VPS/SPS/PPS/SEI extradata */ packetizer_Header(&p_sys->packetizer, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra); } return VLC_SUCCESS; }
/***************************************************************************** * Activate: allocate a chroma function ***************************************************************************** * This function allocates and initializes a chroma function *****************************************************************************/ static int Activate( filter_t *p_filter, int (*pf_build)(filter_t *) ) { filter_sys_t *p_sys; int i_ret = VLC_EGENERIC; p_sys = p_filter->p_sys = calloc( 1, sizeof( *p_sys ) ); if( !p_sys ) return VLC_ENOMEM; filter_owner_t owner = { .video = &filter_video_chain_cbs, .sys = p_filter, }; p_sys->p_chain = filter_chain_NewVideo( p_filter, p_filter->b_allow_fmt_out_change, &owner ); if( !p_sys->p_chain ) { free( p_sys ); return VLC_EGENERIC; } int type = VLC_VAR_INTEGER; if( var_Type( p_filter->obj.parent, "chain-level" ) != 0 ) type |= VLC_VAR_DOINHERIT; var_Create( p_filter, "chain-level", type ); /* Note: atomicity is not actually needed here. */ var_IncInteger( p_filter, "chain-level" ); int level = var_GetInteger( p_filter, "chain-level" ); if( level < 0 || level > CHAIN_LEVEL_MAX ) msg_Err( p_filter, "Too high level of recursion (%d)", level ); else i_ret = pf_build( p_filter ); var_Destroy( p_filter, "chain-level" ); if( i_ret ) { /* Hum ... looks like this really isn't going to work. Too bad. */ if (p_sys->p_video_filter) filter_DelProxyCallbacks( p_filter, p_sys->p_video_filter, RestartFilterCallback ); filter_chain_Delete( p_sys->p_chain ); free( p_sys ); return VLC_EGENERIC; } if( p_filter->b_allow_fmt_out_change ) { es_format_Clean( &p_filter->fmt_out ); es_format_Copy( &p_filter->fmt_out, filter_chain_GetFmtOut( p_sys->p_chain ) ); } /* */ p_filter->pf_video_filter = Chain; return VLC_SUCCESS; }
static void transcode_video_filter_init( sout_stream_t *p_stream, sout_stream_id_t *id ) { id->p_f_chain = filter_chain_New( p_stream, "video filter2", false, transcode_video_filter_allocation_init, transcode_video_filter_allocation_clear, p_stream->p_sys ); /* Deinterlace */ if( p_stream->p_sys->b_deinterlace ) { filter_chain_AppendFilter( id->p_f_chain, p_stream->p_sys->psz_deinterlace, p_stream->p_sys->p_deinterlace_cfg, &id->p_decoder->fmt_out, &id->p_decoder->fmt_out ); } /* Take care of the scaling and chroma conversions */ if( ( id->p_decoder->fmt_out.video.i_chroma != id->p_encoder->fmt_in.video.i_chroma ) || ( id->p_decoder->fmt_out.video.i_width != id->p_encoder->fmt_in.video.i_width ) || ( id->p_decoder->fmt_out.video.i_height != id->p_encoder->fmt_in.video.i_height ) ) { filter_chain_AppendFilter( id->p_f_chain, NULL, NULL, &id->p_decoder->fmt_out, &id->p_encoder->fmt_in ); } if( p_stream->p_sys->psz_vf2 ) { const es_format_t *p_fmt_out; id->p_uf_chain = filter_chain_New( p_stream, "video filter2", true, transcode_video_filter_allocation_init, transcode_video_filter_allocation_clear, p_stream->p_sys ); filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in, &id->p_encoder->fmt_in ); filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 ); p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain ); es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out ); id->p_encoder->fmt_out.video.i_width = id->p_encoder->fmt_in.video.i_width; id->p_encoder->fmt_out.video.i_height = id->p_encoder->fmt_in.video.i_height; id->p_encoder->fmt_out.video.i_sar_num = id->p_encoder->fmt_in.video.i_sar_num; id->p_encoder->fmt_out.video.i_sar_den = id->p_encoder->fmt_in.video.i_sar_den; } }
/** * Filter chain reinitialisation */ void filter_chain_Reset( filter_chain_t *p_chain, const es_format_t *p_fmt_in, const es_format_t *p_fmt_out ) { filter_t *p_filter; while( (p_filter = &p_chain->first->filter) != NULL ) filter_chain_DeleteFilterInternal( p_chain, p_filter ); if( p_fmt_in ) { es_format_Clean( &p_chain->fmt_in ); es_format_Copy( &p_chain->fmt_in, p_fmt_in ); } if( p_fmt_out ) { es_format_Clean( &p_chain->fmt_out ); es_format_Copy( &p_chain->fmt_out, p_fmt_out ); } }
/***************************************************************************** * Open: probe the packetizer and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_VC1 ) return VLC_EGENERIC; p_dec->pf_packetize = Packetize; /* Create the output format */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->p_sys = p_sys = (decoder_sys_t *)malloc( sizeof( decoder_sys_t ) ); // sunqueen modify if( unlikely( !p_sys ) ) return VLC_ENOMEM; packetizer_Init( &p_sys->packetizer, p_vc1_startcode, sizeof(p_vc1_startcode), NULL, 0, 4, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_sequence_header = false; p_sys->sh.p_sh = NULL; p_sys->b_entry_point = false; p_sys->ep.p_ep = NULL; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; p_sys->b_frame = false; p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; p_sys->i_interpolated_dts = VLC_TS_INVALID; p_sys->b_check_startcode = p_dec->fmt_in.b_packetized; if( p_dec->fmt_out.i_extra > 0 ) { uint8_t *p_extra = (uint8_t *)p_dec->fmt_out.p_extra; // sunqueen modify /* With (some) ASF the first byte has to be stripped */ if( p_extra[0] != 0x00 ) { memcpy( &p_extra[0], &p_extra[1], p_dec->fmt_out.i_extra - 1 ); p_dec->fmt_out.i_extra--; } /* */ if( p_dec->fmt_out.i_extra > 0 ) packetizer_Header( &p_sys->packetizer, (const uint8_t *)p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); // sunqueen modify } return VLC_SUCCESS; }
static int BuildFilterChain( filter_t *p_filter ) { es_format_t fmt_mid; int i_ret = VLC_EGENERIC; filter_sys_t *p_sys = p_filter->p_sys; /* Now try chroma format list */ const vlc_fourcc_t *pi_allowed_chromas = get_allowed_chromas( p_filter ); for( int i = 0; pi_allowed_chromas[i]; i++ ) { filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); const vlc_fourcc_t i_chroma = pi_allowed_chromas[i]; if( i_chroma == p_filter->fmt_in.i_codec || i_chroma == p_filter->fmt_out.i_codec ) continue; msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man", (char*)&i_chroma ); es_format_Copy( &fmt_mid, &p_filter->fmt_in ); fmt_mid.i_codec = fmt_mid.video.i_chroma = i_chroma; fmt_mid.video.i_rmask = 0; fmt_mid.video.i_gmask = 0; fmt_mid.video.i_bmask = 0; video_format_FixRgb(&fmt_mid.video); if( filter_chain_AppendConverter( p_sys->p_chain, NULL, &fmt_mid ) == VLC_SUCCESS ) { p_sys->p_video_filter = filter_chain_AppendFilter( p_sys->p_chain, p_filter->psz_name, p_filter->p_cfg, &fmt_mid, &fmt_mid ); if( p_sys->p_video_filter ) { filter_AddProxyCallbacks( p_filter, p_sys->p_video_filter, RestartFilterCallback ); if (p_sys->p_video_filter->pf_video_mouse != NULL) p_filter->pf_video_mouse = ChainMouse; es_format_Clean( &fmt_mid ); i_ret = VLC_SUCCESS; break; } } es_format_Clean( &fmt_mid ); } if( i_ret != VLC_SUCCESS ) filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); return i_ret; }
static void transcode_video_filter_init( sout_stream_t *p_stream, sout_stream_id_t *id ) { es_format_t *p_fmt_out = &id->p_decoder->fmt_out; id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec; id->p_f_chain = filter_chain_New( p_stream, "video filter2", false, transcode_video_filter_allocation_init, transcode_video_filter_allocation_clear, p_stream->p_sys ); filter_chain_Reset( id->p_f_chain, p_fmt_out, p_fmt_out ); /* Deinterlace */ if( p_stream->p_sys->b_deinterlace ) { filter_chain_AppendFilter( id->p_f_chain, p_stream->p_sys->psz_deinterlace, p_stream->p_sys->p_deinterlace_cfg, &id->p_decoder->fmt_out, &id->p_decoder->fmt_out ); p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain ); } /* Check that we have visible_width/height*/ if( !p_fmt_out->video.i_visible_height ) p_fmt_out->video.i_visible_height = p_fmt_out->video.i_height; if( !p_fmt_out->video.i_visible_width ) p_fmt_out->video.i_visible_width = p_fmt_out->video.i_width; if( p_stream->p_sys->psz_vf2 ) { id->p_uf_chain = filter_chain_New( p_stream, "video filter2", true, transcode_video_filter_allocation_init, transcode_video_filter_allocation_clear, p_stream->p_sys ); filter_chain_Reset( id->p_uf_chain, p_fmt_out, &id->p_encoder->fmt_in ); filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 ); p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain ); es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out ); id->p_encoder->fmt_out.video.i_width = id->p_encoder->fmt_in.video.i_width; id->p_encoder->fmt_out.video.i_height = id->p_encoder->fmt_in.video.i_height; id->p_encoder->fmt_out.video.i_sar_num = id->p_encoder->fmt_in.video.i_sar_num; id->p_encoder->fmt_out.video.i_sar_den = id->p_encoder->fmt_in.video.i_sar_den; } }
/***************************************************************************** * OpenDecoder: Open the decoder *****************************************************************************/ static int OpenDecoderCommon( vlc_object_t *p_this, bool b_force_dump ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; char psz_file[ PATH_MAX ]; vlc_value_t val; /* 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 ) { return VLC_ENOMEM; } snprintf( psz_file, sizeof( psz_file), "stream.%p", p_dec ); #ifndef UNDER_CE if( !b_force_dump ) { var_Create( p_dec, "dummy-save-es", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); var_Get( p_dec, "dummy-save-es", &val ); b_force_dump = val.b_bool; } if( b_force_dump ) { p_sys->i_fd = utf8_open( psz_file, O_WRONLY | O_CREAT | O_TRUNC, 00644 ); if( p_sys->i_fd == -1 ) { msg_Err( p_dec, "cannot create `%s'", psz_file ); free( p_sys ); return VLC_EGENERIC; } msg_Dbg( p_dec, "dumping stream to file `%s'", psz_file ); } else #endif { p_sys->i_fd = -1; } /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_decode_audio = (aout_buffer_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **)) DecodeBlock; es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); return VLC_SUCCESS; }
/** * Common initialization for decoder and packetizer */ static int OpenCommon( decoder_t *p_dec, bool b_packetizer ) { const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription( p_dec->fmt_in.i_codec ); if( dsc == NULL || dsc->plane_count == 0 ) return VLC_EGENERIC; if( p_dec->fmt_in.video.i_width <= 0 || p_dec->fmt_in.video.i_height == 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ decoder_sys_t *p_sys = calloc(1, sizeof(*p_sys)); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; if( !p_dec->fmt_in.video.i_visible_width ) p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width; if( !p_dec->fmt_in.video.i_visible_height ) p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height; if ( !b_packetizer ) es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } for( unsigned i = 0; i < dsc->plane_count; i++ ) { unsigned pitch = p_dec->fmt_in.video.i_width * dsc->pixel_size * dsc->p[i].w.num / dsc->p[i].w.den; unsigned lines = p_dec->fmt_in.video.i_height * dsc->p[i].h.num / dsc->p[i].h.den; p_sys->pitches[i] = pitch; p_sys->lines[i] = lines; p_sys->size += pitch * lines; } p_dec->p_sys = p_sys; return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_MP4V ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) return VLC_ENOMEM; memset( p_sys, 0, sizeof(decoder_sys_t) ); /* Misc init */ packetizer_Init( &p_sys->packetizer, p_mp4v_startcode, sizeof(p_mp4v_startcode), startcode_FindAnnexB, NULL, 0, 4, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_MP4V; free(p_dec->fmt_out.p_extra); if( p_dec->fmt_in.i_extra ) { /* We have a vol */ p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = xmalloc( p_dec->fmt_in.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); msg_Dbg( p_dec, "opening with vol size: %d", p_dec->fmt_in.i_extra ); ParseVOL( p_dec, &p_dec->fmt_out, p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); } else { /* No vol, we'll have to look for one later on */ p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = 0; } /* Set callback */ p_dec->pf_packetize = Packetize; p_dec->pf_flush = PacketizeFlush; return VLC_SUCCESS; }
static void EsFormatMergeSize( es_format_t *p_dst, const es_format_t *p_base, const es_format_t *p_size ) { es_format_Copy( p_dst, p_base ); p_dst->video.i_width = p_size->video.i_width; p_dst->video.i_height = p_size->video.i_height; p_dst->video.i_visible_width = p_size->video.i_visible_width; p_dst->video.i_visible_height = p_size->video.i_visible_height; }
static int Open(vlc_object_t *obj) { decoder_t *dec = (decoder_t *)obj; if (dec->fmt_in.i_codec != VLC_CODEC_XWD) return VLC_EGENERIC; dec->pf_decode = Decode; es_format_Copy(&dec->fmt_out, &dec->fmt_in); dec->fmt_out.i_codec = VLC_CODEC_RGB32; return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_cat != AUDIO_ES && p_dec->fmt_in.i_cat != VIDEO_ES && p_dec->fmt_in.i_cat != SPU_ES ) { msg_Err( p_dec, "invalid ES type" ); return VLC_EGENERIC; } if( p_dec->fmt_in.i_cat == SPU_ES ) p_dec->pf_packetize = PacketizeSub; else p_dec->pf_packetize = Packetize; /* Create the output format */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); /* Fix the value of the fourcc for audio */ if( p_dec->fmt_in.i_cat == AUDIO_ES ) { p_dec->fmt_out.i_codec = vlc_fourcc_GetCodecAudio( p_dec->fmt_in.i_codec, p_dec->fmt_in.audio.i_bitspersample ); if( !p_dec->fmt_out.i_codec ) { msg_Err( p_dec, "unknown raw audio sample size" ); return VLC_EGENERIC; } } p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) ); p_sys->p_block = NULL; switch( p_dec->fmt_in.i_codec ) { case VLC_CODEC_WMV3: p_sys->pf_parse = ParseWMV3; break; default: p_sys->pf_parse = NULL; break; } return VLC_SUCCESS; }
static sout_stream_id_sys_t * Add( sout_stream_t *p_stream, const es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_stream->p_sys; sout_stream_id_sys_t *p_es = malloc( sizeof(sout_stream_id_sys_t) ); if( unlikely(p_es == NULL) ) return NULL; es_format_Copy( &p_es->fmt, p_fmt ); p_es->id = NULL; p_es->i_last = VLC_TS_INVALID; p_es->b_error = false; TAB_APPEND( p_sys->i_es_num, p_sys->pp_es, p_es ); return p_es; }
static void EsFormatMergeSize( es_format_t *p_dst, const es_format_t *p_base, const es_format_t *p_size ) { es_format_Copy( p_dst, p_base ); p_dst->video.i_width = p_size->video.i_width; p_dst->video.i_height = p_size->video.i_height; p_dst->video.i_visible_width = p_size->video.i_visible_width; p_dst->video.i_visible_height = p_size->video.i_visible_height; p_dst->video.i_x_offset = p_size->video.i_x_offset; p_dst->video.i_y_offset = p_size->video.i_y_offset; p_dst->video.orientation = p_size->video.orientation; p_dst->video.i_sar_num = p_size->video.i_sar_num; p_dst->video.i_sar_den = p_size->video.i_sar_den; }
static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_id_t *id; es_format_t *p_fmt_copy; msg_Dbg( p_stream, "Adding a stream" ); p_fmt_copy = (es_format_t *)malloc(sizeof(es_format_t)); // sunqueen modify es_format_Copy( p_fmt_copy, p_fmt ); TAB_APPEND( (es_format_t **), p_sys->data->i_es, p_sys->data->es, p_fmt_copy ); // sunqueen modify if( p_sys->i_stream_start <= 0 ) p_sys->i_stream_start = mdate(); id = (sout_stream_id_t *)malloc( sizeof( sout_stream_id_t ) ); // sunqueen modify return id; }
static sout_stream_id_t *Add( sout_stream_t *p_stream, es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = p_stream->p_sys; sout_stream_id_t *id; id = malloc( sizeof(*id) ); if( !id ) return NULL; es_format_Copy( &id->fmt, p_fmt ); id->p_first = NULL; id->pp_last = &id->p_first; id->id = NULL; id->b_wait_key = true; id->b_wait_start = true; TAB_APPEND( p_sys->i_id, p_sys->id, id ); return id; }
/***************************************************************************** * Sout callbacks *****************************************************************************/ static sout_stream_id_sys_t *Add(sout_stream_t *p_stream, const es_format_t *p_fmt) { sout_stream_sys_t *p_sys = p_stream->p_sys; if (!p_sys->b_has_video) { if (p_fmt->i_cat != AUDIO_ES) return NULL; } sout_stream_id_sys_t *p_sys_id = (sout_stream_id_sys_t *)malloc( sizeof(sout_stream_id_sys_t) ); if (p_sys_id != NULL) { es_format_Copy( &p_sys_id->fmt, p_fmt ); p_sys_id->p_sub_id = NULL; p_sys->streams.push_back( p_sys_id ); p_sys->es_changed = true; } return p_sys_id; }
/***************************************************************************** * sout_MuxAddStream: *****************************************************************************/ sout_input_t *sout_MuxAddStream( sout_mux_t *p_mux, const es_format_t *p_fmt ) { sout_input_t *p_input; if( !p_mux->b_add_stream_any_time && !p_mux->b_waiting_stream ) { msg_Err( p_mux, "cannot add a new stream (unsupported while muxing " "to this format). You can try increasing sout-mux-caching value" ); return NULL; } msg_Dbg( p_mux, "adding a new input" ); /* create a new sout input */ p_input = malloc( sizeof( sout_input_t ) ); if( !p_input ) return NULL; // FIXME: remove either fmt or p_fmt... es_format_Copy( &p_input->fmt, p_fmt ); p_input->p_fmt = &p_input->fmt; p_input->p_fifo = block_FifoNew(); p_input->p_sys = NULL; TAB_APPEND( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input ); if( p_mux->pf_addstream( p_mux, p_input ) < 0 ) { msg_Err( p_mux, "cannot add this stream" ); TAB_REMOVE( p_mux->i_nb_inputs, p_mux->pp_inputs, p_input ); block_FifoRelease( p_input->p_fifo ); es_format_Clean( &p_input->fmt ); free( p_input ); return NULL; } return p_input; }
/***************************************************************************** * Open: *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_CODEC_MJPG ) return VLC_EGENERIC; p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); if( !p_dec->p_sys ) return VLC_ENOMEM; p_sys->i_next_block_flags = 0; if( p_dec->fmt_in.video.i_frame_rate && p_dec->fmt_in.video.i_frame_rate_base ) { date_Init( &p_sys->date, p_dec->fmt_in.video.i_frame_rate, p_dec->fmt_in.video.i_frame_rate_base ); } else date_Init( &p_sys->date, 30000, 1001 ); es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); /* Misc init */ packetizer_Init( &p_sys->packetizer, p_mjpg_startcode, sizeof(p_mjpg_startcode), startcode_Find, NULL, 0, 295, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_dec->pf_packetize = Packetize; p_dec->pf_flush = PacketizeFlush; p_dec->pf_get_cc = NULL; return VLC_SUCCESS; }
/***************************************************************************** * Open: probe the packetizer and return score * When opening after demux, the packetizer is only loaded AFTER the decoder * That means that what you set in fmt_out is ignored by the decoder in this special case *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'h', '2', '6', '4') && p_dec->fmt_in.i_codec != VLC_FOURCC( 'H', '2', '6', '4') && p_dec->fmt_in.i_codec != VLC_FOURCC( 'V', 'S', 'S', 'H') && p_dec->fmt_in.i_codec != VLC_FOURCC( 'v', 's', 's', 'h') && p_dec->fmt_in.i_codec != VLC_FOURCC( 'D', 'A', 'V', 'C') && ( p_dec->fmt_in.i_codec != VLC_FOURCC( 'a', 'v', 'c', '1') || p_dec->fmt_in.i_extra < 7 ) ) { return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) { msg_Err( p_dec, "out of memory" ); return VLC_EGENERIC; } p_sys->i_state = STATE_NOSYNC; p_sys->i_offset = 0; p_sys->startcode[0] = 0; p_sys->startcode[1] = 0; p_sys->startcode[2] = 0; p_sys->startcode[3] = 1; p_sys->bytestream = block_BytestreamInit( p_dec ); p_sys->b_slice = VLC_FALSE; p_sys->p_frame = NULL; p_sys->b_sps = VLC_FALSE; p_sys->b_pps = VLC_FALSE; p_sys->p_sps = 0; p_sys->p_pps = 0; p_sys->b_header= VLC_FALSE; p_sys->slice.i_nal_type = -1; p_sys->slice.i_nal_ref_idc = -1; p_sys->slice.i_idr_pic_id = -1; p_sys->slice.i_frame_num = -1; p_sys->slice.i_frame_type = 0; p_sys->slice.i_pic_parameter_set_id = -1; p_sys->slice.i_field_pic_flag = 0; p_sys->slice.i_bottom_field_flag = -1; p_sys->slice.i_pic_order_cnt_lsb = -1; p_sys->slice.i_delta_pic_order_cnt_bottom = -1; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_FOURCC( 'h', '2', '6', '4' ); if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'a', 'v', 'c', '1' ) ) { /* This type of stream is produced by mp4 and matroska * when we want to store it in another streamformat, you need to convert * The fmt_in.p_extra should ALWAYS contain the avcC * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ uint8_t *p = &((uint8_t*)p_dec->fmt_in.p_extra)[4]; int i_sps, i_pps; int i; /* Parse avcC */ p_sys->i_avcC_length_size = 1 + ((*p++)&0x03); /* Read SPS */ i_sps = (*p++)&0x1f; for( i = 0; i < i_sps; i++ ) { int i_length = GetWBE( p ); block_t *p_sps = nal_get_annexeb( p_dec, p + 2, i_length ); p_sys->p_sps = block_Duplicate( p_sps ); p_sps->i_pts = p_sps->i_dts = mdate(); ParseNALBlock( p_dec, p_sps ); p += 2 + i_length; } /* Read PPS */ i_pps = *p++; for( i = 0; i < i_pps; i++ ) { int i_length = GetWBE( p ); block_t *p_pps = nal_get_annexeb( p_dec, p + 2, i_length ); p_sys->p_pps = block_Duplicate( p_pps ); p_pps->i_pts = p_pps->i_dts = mdate(); ParseNALBlock( p_dec, p_pps ); p += 2 + i_length; } msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d", p_sys->i_avcC_length_size, i_sps, i_pps ); /* FIXME: FFMPEG isn't happy at all if you leave this */ if( p_dec->fmt_out.i_extra ) free( p_dec->fmt_out.p_extra ); p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = NULL; /* Set the new extradata */ p_dec->fmt_out.i_extra = p_sys->p_pps->i_buffer + p_sys->p_sps->i_buffer; p_dec->fmt_out.p_extra = (uint8_t*)malloc( p_dec->fmt_out.i_extra ); memcpy( (uint8_t*)p_dec->fmt_out.p_extra, p_sys->p_sps->p_buffer, p_sys->p_sps->i_buffer); memcpy( (uint8_t*)p_dec->fmt_out.p_extra+p_sys->p_sps->i_buffer, p_sys->p_pps->p_buffer, p_sys->p_pps->i_buffer); p_sys->b_header = VLC_TRUE; /* Set callback */ p_dec->pf_packetize = PacketizeAVC1; } else { /* This type of stream contains data with 3 of 4 byte startcodes * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes * The fmt_out.p_extra should be the same */ /* Set callback */ p_dec->pf_packetize = Packetize; /* */ if( p_dec->fmt_in.i_extra > 0 ) { block_t *p_init = block_New( p_dec, p_dec->fmt_in.i_extra ); block_t *p_pic; memcpy( p_init->p_buffer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); while( ( p_pic = Packetize( p_dec, &p_init ) ) ) { /* Should not occur because we should only receive SPS/PPS */ block_Release( p_pic ); } } } return VLC_SUCCESS; }
static int Open(filter_t *filter) { int32_t frame_duration = filter->fmt_in.video.i_frame_rate != 0 ? (int64_t)1000000 * filter->fmt_in.video.i_frame_rate_base / filter->fmt_in.video.i_frame_rate : 0; MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = { { MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param) }, MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV, 2, { 3, frame_duration } }; int ret = VLC_SUCCESS; MMAL_STATUS_T status; filter_sys_t *sys; msg_Dbg(filter, "Try to open mmal_deinterlace filter. frame_duration: %d!", frame_duration); if (filter->fmt_in.video.i_chroma != VLC_CODEC_MMAL_OPAQUE) return VLC_EGENERIC; if (filter->fmt_out.video.i_chroma != VLC_CODEC_MMAL_OPAQUE) return VLC_EGENERIC; sys = calloc(1, sizeof(filter_sys_t)); if (!sys) return VLC_ENOMEM; filter->p_sys = sys; bcm_host_init(); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_DEINTERLACE, &sys->component); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to create MMAL component %s (status=%"PRIx32" %s)", MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } status = mmal_port_parameter_set(sys->component->output[0], &imfx_param.hdr); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to configure MMAL component %s (status=%"PRIx32" %s)", MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)filter; status = mmal_port_enable(sys->component->control, control_port_cb); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable control port %s (status=%"PRIx32" %s)", sys->component->control->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->input = sys->component->input[0]; sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)filter; if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) sys->input->format->encoding = MMAL_ENCODING_OPAQUE; sys->input->format->es->video.width = filter->fmt_in.video.i_width; sys->input->format->es->video.height = filter->fmt_in.video.i_height; sys->input->format->es->video.crop.x = 0; sys->input->format->es->video.crop.y = 0; sys->input->format->es->video.crop.width = filter->fmt_in.video.i_width; sys->input->format->es->video.crop.height = filter->fmt_in.video.i_height; sys->input->format->es->video.par.num = filter->fmt_in.video.i_sar_num; sys->input->format->es->video.par.den = filter->fmt_in.video.i_sar_den; es_format_Copy(&filter->fmt_out, &filter->fmt_in); filter->fmt_out.video.i_frame_rate *= 2; status = mmal_port_format_commit(sys->input); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to commit format for input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->input->buffer_size = sys->input->buffer_size_recommended; sys->input->buffer_num = sys->input->buffer_num_recommended; if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) { MMAL_PARAMETER_BOOLEAN_T zero_copy = { { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) }, 1 }; status = mmal_port_parameter_set(sys->input, &zero_copy.hdr); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); goto out; } } status = mmal_port_enable(sys->input, input_port_cb); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->output = sys->component->output[0]; sys->output->userdata = (struct MMAL_PORT_USERDATA_T *)filter; mmal_format_full_copy(sys->output->format, sys->input->format); status = mmal_port_format_commit(sys->output); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to commit format for output port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->output->buffer_num = 3; if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) { MMAL_PARAMETER_BOOLEAN_T zero_copy = { { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) }, 1 }; status = mmal_port_parameter_set(sys->output, &zero_copy.hdr); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)", sys->output->name, status, mmal_status_to_string(status)); goto out; } } status = mmal_port_enable(sys->output, output_port_cb); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable output port %s (status=%"PRIx32" %s)", sys->output->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } status = mmal_component_enable(sys->component); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable component %s (status=%"PRIx32" %s)", sys->component->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->filtered_pictures = mmal_queue_create(); filter->pf_video_filter = deinterlace; filter->pf_video_flush = flush; vlc_mutex_init_recursive(&sys->mutex); vlc_mutex_init(&sys->buffer_cond_mutex); vlc_cond_init(&sys->buffer_cond); out: if (ret != VLC_SUCCESS) Close(filter); return ret; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; switch( p_dec->fmt_in.i_codec ) { /* Planar YUV */ case VLC_CODEC_I444: case VLC_CODEC_J444: case VLC_CODEC_I440: case VLC_CODEC_J440: case VLC_CODEC_I422: case VLC_CODEC_J422: case VLC_CODEC_I420: case VLC_CODEC_J420: case VLC_CODEC_YV12: case VLC_CODEC_YV9: case VLC_CODEC_I411: case VLC_CODEC_I410: case VLC_CODEC_GREY: case VLC_CODEC_YUVP: case VLC_CODEC_NV12: case VLC_CODEC_NV21: case VLC_CODEC_I422_10L: case VLC_CODEC_I422_10B: /* Packed YUV */ case VLC_CODEC_YUYV: case VLC_CODEC_YVYU: case VLC_CODEC_UYVY: case VLC_CODEC_VYUY: /* RGB */ case VLC_CODEC_RGB32: case VLC_CODEC_RGB24: case VLC_CODEC_RGB16: case VLC_CODEC_RGB15: case VLC_CODEC_RGB8: case VLC_CODEC_RGBP: case VLC_CODEC_RGBA: break; default: return VLC_EGENERIC; } /* 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 ) return VLC_ENOMEM; /* Misc init */ p_dec->p_sys->b_packetizer = false; p_sys->b_invert = false; if( (int)p_dec->fmt_in.video.i_height < 0 ) { /* Frames are coded from bottom to top */ p_dec->fmt_in.video.i_height = (unsigned int)(-(int)p_dec->fmt_in.video.i_height); p_sys->b_invert = true; } if( !p_dec->fmt_in.video.i_visible_width ) p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width; if( !p_dec->fmt_in.video.i_visible_height ) p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height; if( p_dec->fmt_in.video.i_visible_width <= 0 || p_dec->fmt_in.video.i_visible_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } /* Find out p_vdec->i_raw_size */ video_format_Setup( &p_dec->fmt_out.video, p_dec->fmt_in.i_codec, p_dec->fmt_in.video.i_visible_width, p_dec->fmt_in.video.i_visible_height, p_dec->fmt_in.video.i_sar_num, p_dec->fmt_in.video.i_sar_den ); picture_t picture; picture_Setup( &picture, p_dec->fmt_out.i_codec, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height, 0, 1 ); p_sys->i_raw_size = 0; for( int i = 0; i < picture.i_planes; i++ ) { p_sys->i_raw_size += picture.p[i].i_visible_pitch * picture.p[i].i_visible_lines; p_sys->planes[i] = picture.p[i]; } if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den ) { p_dec->fmt_out.video.i_sar_num = 1; p_dec->fmt_out.video.i_sar_den = 1; } /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; return VLC_SUCCESS; }
static sout_stream_id_sys_t * Add( sout_stream_t *p_stream, const es_format_t *p_fmt ) { sout_stream_sys_t *p_sys = p_stream->p_sys; bridge_t *p_bridge; bridged_es_t *p_es; char *psz_chain; int i; if( p_sys->b_inited || p_fmt->i_cat != VIDEO_ES ) return NULL; /* Create decoder object */ p_sys->p_decoder = vlc_object_create( p_stream, sizeof( decoder_t ) ); if( !p_sys->p_decoder ) return NULL; p_sys->p_decoder->p_module = NULL; p_sys->p_decoder->fmt_in = *p_fmt; p_sys->p_decoder->b_frame_drop_allowed = true; p_sys->p_decoder->fmt_out = p_sys->p_decoder->fmt_in; p_sys->p_decoder->fmt_out.i_extra = 0; p_sys->p_decoder->fmt_out.p_extra = 0; p_sys->p_decoder->pf_decode_video = 0; p_sys->p_decoder->pf_vout_format_update = video_update_format_decoder; p_sys->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder; p_sys->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) ); if( !p_sys->p_decoder->p_owner ) { vlc_object_release( p_sys->p_decoder ); return NULL; } p_sys->p_decoder->p_owner->video = p_fmt->video; //p_sys->p_decoder->p_cfg = p_sys->p_video_cfg; p_sys->p_decoder->p_module = module_need( p_sys->p_decoder, "decoder", "$codec", false ); if( !p_sys->p_decoder->p_module || !p_sys->p_decoder->pf_decode_video ) { if( p_sys->p_decoder->p_module ) { msg_Err( p_stream, "instanciated a non video decoder" ); module_unneed( p_sys->p_decoder, p_sys->p_decoder->p_module ); } else { msg_Err( p_stream, "cannot find decoder" ); } free( p_sys->p_decoder->p_owner ); vlc_object_release( p_sys->p_decoder ); return NULL; } p_sys->b_inited = true; vlc_global_lock( VLC_MOSAIC_MUTEX ); p_bridge = GetBridge( p_stream ); if ( p_bridge == NULL ) { vlc_object_t *p_libvlc = VLC_OBJECT( p_stream->obj.libvlc ); vlc_value_t val; p_bridge = xmalloc( sizeof( bridge_t ) ); var_Create( p_libvlc, "mosaic-struct", VLC_VAR_ADDRESS ); val.p_address = p_bridge; var_Set( p_libvlc, "mosaic-struct", val ); p_bridge->i_es_num = 0; p_bridge->pp_es = NULL; } for ( i = 0; i < p_bridge->i_es_num; i++ ) { if ( p_bridge->pp_es[i]->b_empty ) break; } if ( i == p_bridge->i_es_num ) { p_bridge->pp_es = xrealloc( p_bridge->pp_es, (p_bridge->i_es_num + 1) * sizeof(bridged_es_t *) ); p_bridge->i_es_num++; p_bridge->pp_es[i] = xmalloc( sizeof(bridged_es_t) ); } p_sys->p_es = p_es = p_bridge->pp_es[i]; p_es->i_alpha = var_GetInteger( p_stream, CFG_PREFIX "alpha" ); p_es->i_x = var_GetInteger( p_stream, CFG_PREFIX "x" ); p_es->i_y = var_GetInteger( p_stream, CFG_PREFIX "y" ); //p_es->fmt = *p_fmt; p_es->psz_id = p_sys->psz_id; p_es->p_picture = NULL; p_es->pp_last = &p_es->p_picture; p_es->b_empty = false; vlc_global_unlock( VLC_MOSAIC_MUTEX ); if ( p_sys->i_height || p_sys->i_width ) { p_sys->p_image = image_HandlerCreate( p_stream ); } else { p_sys->p_image = NULL; } msg_Dbg( p_stream, "mosaic bridge id=%s pos=%d", p_es->psz_id, i ); /* Create user specified video filters */ psz_chain = var_GetNonEmptyString( p_stream, CFG_PREFIX "vfilter" ); msg_Dbg( p_stream, "psz_chain: %s", psz_chain ); if( psz_chain ) { filter_owner_t owner = { .sys = p_sys->p_decoder->p_owner, .video = { .buffer_new = video_new_buffer_filter, }, }; p_sys->p_vf2 = filter_chain_NewVideo( p_stream, false, &owner ); es_format_t fmt; es_format_Copy( &fmt, &p_sys->p_decoder->fmt_out ); if( p_sys->i_chroma ) fmt.video.i_chroma = p_sys->i_chroma; filter_chain_Reset( p_sys->p_vf2, &fmt, &fmt ); filter_chain_AppendFromString( p_sys->p_vf2, psz_chain ); free( psz_chain ); } else {
/***************************************************************************** * Open: probe the packetizer and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to choose. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_cat != AUDIO_ES && p_dec->fmt_in.i_cat != VIDEO_ES && p_dec->fmt_in.i_cat != SPU_ES ) { msg_Err( p_dec, "invalid ES type" ); return VLC_EGENERIC; } if( p_dec->fmt_in.i_cat == SPU_ES ) p_dec->pf_packetize = PacketizeSub; else p_dec->pf_packetize = Packetize; /* Create the output format */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); /* Fix the value of the fourcc */ switch( p_dec->fmt_in.i_codec ) { /* video */ case VLC_FOURCC( 'm', '4', 's', '2'): case VLC_FOURCC( 'M', '4', 'S', '2'): case VLC_FOURCC( 'm', 'p', '4', 's'): case VLC_FOURCC( 'M', 'P', '4', 'S'): case VLC_FOURCC( 'D', 'I', 'V', 'X'): case VLC_FOURCC( 'd', 'i', 'v', 'x'): case VLC_FOURCC( 'X', 'V', 'I', 'D'): case VLC_FOURCC( 'X', 'v', 'i', 'D'): case VLC_FOURCC( 'x', 'v', 'i', 'd'): case VLC_FOURCC( 'D', 'X', '5', '0'): case VLC_FOURCC( 0x04, 0, 0, 0): case VLC_FOURCC( '3', 'I', 'V', '2'): p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', '4', 'v'); break; case VLC_FOURCC( 'm', 'p', 'g', '1' ): case VLC_FOURCC( 'm', 'p', 'g', '2' ): case VLC_FOURCC( 'm', 'p', '1', 'v' ): case VLC_FOURCC( 'm', 'p', '2', 'v' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'm', 'p', 'g', 'v' ); break; case VLC_FOURCC( 'd', 'i', 'v', '1' ): case VLC_FOURCC( 'M', 'P', 'G', '4' ): case VLC_FOURCC( 'm', 'p', 'g', '4' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '1' ); break; case VLC_FOURCC( 'd', 'i', 'v', '2' ): case VLC_FOURCC( 'M', 'P', '4', '2' ): case VLC_FOURCC( 'm', 'p', '4', '2' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '2' ); break; case VLC_FOURCC( 'd', 'i', 'v', '3' ): case VLC_FOURCC( 'd', 'i', 'v', '4' ): case VLC_FOURCC( 'D', 'I', 'V', '4' ): case VLC_FOURCC( 'd', 'i', 'v', '5' ): case VLC_FOURCC( 'D', 'I', 'V', '5' ): case VLC_FOURCC( 'd', 'i', 'v', '6' ): case VLC_FOURCC( 'D', 'I', 'V', '6' ): case VLC_FOURCC( 'M', 'P', '4', '3' ): case VLC_FOURCC( 'm', 'p', '4', '3' ): case VLC_FOURCC( 'm', 'p', 'g', '3' ): case VLC_FOURCC( 'M', 'P', 'G', '3' ): case VLC_FOURCC( 'A', 'P', '4', '1' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'D', 'I', 'V', '3' ); break; case VLC_FOURCC( 'h', '2', '6', '3' ): case VLC_FOURCC( 'U', '2', '6', '3' ): case VLC_FOURCC( 'u', '2', '6', '3' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'H', '2', '6', '3' ); break; case VLC_FOURCC( 'i', '2', '6', '3' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'I', '2', '6', '3' ); break; case VLC_FOURCC( 'm', 'j', 'p', 'g' ): case VLC_FOURCC( 'm', 'j', 'p', 'a' ): case VLC_FOURCC( 'j', 'p', 'e', 'g' ): case VLC_FOURCC( 'J', 'P', 'E', 'G' ): case VLC_FOURCC( 'J', 'F', 'I', 'F' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'M', 'J', 'P', 'G' ); break; case VLC_FOURCC( 'd', 'v', 's', 'd' ): case VLC_FOURCC( 'D', 'V', 'S', 'D' ): case VLC_FOURCC( 'd', 'v', 'h', 'd' ): p_dec->fmt_out.i_codec = VLC_FOURCC( 'd', 'v', 's', 'l' ); break; /* audio */ case VLC_FOURCC( 'a', 'r', 'a', 'w' ): switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { case 1: p_dec->fmt_out.i_codec = VLC_FOURCC('u','8',' ',' '); break; case 2: p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); break; case 3: p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); break; case 4: p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); break; default: msg_Err( p_dec, "unknown raw audio sample size" ); return VLC_EGENERIC; } break; case VLC_FOURCC( 't', 'w', 'o', 's' ): switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { case 1: p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); break; case 2: p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','b'); break; case 3: p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','b'); break; case 4: p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','b'); break; default: msg_Err( p_dec, "unknown raw audio sample size" ); return VLC_EGENERIC; } break; case VLC_FOURCC( 's', 'o', 'w', 't' ): switch( ( p_dec->fmt_in.audio.i_bitspersample + 7 ) / 8 ) { case 1: p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' '); break; case 2: p_dec->fmt_out.i_codec = VLC_FOURCC('s','1','6','l'); break; case 3: p_dec->fmt_out.i_codec = VLC_FOURCC('s','2','4','l'); break; case 4: p_dec->fmt_out.i_codec = VLC_FOURCC('s','3','2','l'); break; default: msg_Err( p_dec, "unknown raw audio sample size" ); return VLC_EGENERIC; } break; } p_dec->p_sys = p_sys = malloc( sizeof( block_t ) ); p_sys->p_block = NULL; return VLC_SUCCESS; }
static int Activate( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; unsigned i_canvas_width; /* width of output canvas */ unsigned i_canvas_height; /* height of output canvas */ unsigned i_canvas_aspect; /* canvas PictureAspectRatio */ es_format_t fmt; /* target format after up/down conversion */ char psz_croppadd[100]; int i_padd,i_offset; char *psz_aspect, *psz_parser; bool b_padd; unsigned i_fmt_in_aspect; if( !p_filter->b_allow_fmt_out_change ) { msg_Err( p_filter, "Picture format change isn't allowed" ); return VLC_EGENERIC; } if( p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma ) { msg_Err( p_filter, "Input and output chromas don't match" ); return VLC_EGENERIC; } config_ChainParse( p_filter, CFG_PREFIX, ppsz_filter_options, p_filter->p_cfg ); i_canvas_width = var_CreateGetInteger( p_filter, CFG_PREFIX "width" ); i_canvas_height = var_CreateGetInteger( p_filter, CFG_PREFIX "height" ); if( i_canvas_width == 0 || i_canvas_height == 0 ) { msg_Err( p_filter, "Width and height options must be set" ); return VLC_EGENERIC; } if( i_canvas_width & 1 || i_canvas_height & 1 ) { /* If this restriction were ever relaxed, it is very important to * get the field polatiry correct */ msg_Err( p_filter, "Width and height options must be even integers" ); return VLC_EGENERIC; } i_fmt_in_aspect = (int64_t)p_filter->fmt_in.video.i_sar_num * p_filter->fmt_in.video.i_width * VOUT_ASPECT_FACTOR / p_filter->fmt_in.video.i_sar_den / p_filter->fmt_in.video.i_height; psz_aspect = var_CreateGetNonEmptyString( p_filter, CFG_PREFIX "aspect" ); if( psz_aspect ) { psz_parser = strchr( psz_aspect, ':' ); int numerator = atoi( psz_aspect ); int denominator = psz_parser ? atoi( psz_parser+1 ) : 0; denominator = denominator == 0 ? 1 : denominator; i_canvas_aspect = numerator * VOUT_ASPECT_FACTOR / denominator; free( psz_aspect ); if( numerator <= 0 || denominator < 0 ) { msg_Err( p_filter, "Aspect ratio must be strictly positive" ); return VLC_EGENERIC; } } else { /* if there is no user supplied aspect ratio, assume the canvas * has the same sample aspect ratio as the subpicture */ /* aspect = subpic_sar * canvas_width / canvas_height * where subpic_sar = subpic_ph * subpic_par / subpic_pw */ i_canvas_aspect = (uint64_t) p_filter->fmt_in.video.i_height * i_fmt_in_aspect * i_canvas_width / (i_canvas_height * p_filter->fmt_in.video.i_width); } b_padd = var_CreateGetBool( p_filter, CFG_PREFIX "padd" ); filter_sys_t *p_sys = (filter_sys_t *)malloc( sizeof( filter_sys_t ) ); if( !p_sys ) return VLC_ENOMEM; p_filter->p_sys = p_sys; p_sys->p_chain = filter_chain_New( p_filter, "video filter2", true, alloc_init, NULL, p_filter ); if( !p_sys->p_chain ) { msg_Err( p_filter, "Could not allocate filter chain" ); free( p_sys ); return VLC_EGENERIC; } es_format_Copy( &fmt, &p_filter->fmt_in ); /* one dimension will end up with one of the following: */ fmt.video.i_width = i_canvas_width; fmt.video.i_height = i_canvas_height; if( b_padd ) { /* Padd */ if( i_canvas_aspect > i_fmt_in_aspect ) { /* The canvas has a wider aspect than the subpicture: * ie, pillarbox the [scaled] subpicture */ /* The following is derived form: * width = upconverted_subpic_height * subpic_par / canvas_sar * where canvas_sar = canvas_width / (canvas_height * canvas_par) * then simplify */ fmt.video.i_width = i_canvas_width * i_fmt_in_aspect / i_canvas_aspect; if( fmt.video.i_width & 1 ) fmt.video.i_width -= 1; i_padd = (i_canvas_width - fmt.video.i_width) / 2; i_offset = (i_padd & 1); _snprintf( psz_croppadd, 100, "croppadd{paddleft=%d,paddright=%d}", i_padd - i_offset, i_padd + i_offset ); // sunqueen modify } else { /* The canvas has a taller aspect than the subpicture: * ie, letterbox the [scaled] subpicture */ fmt.video.i_height = i_canvas_height * i_canvas_aspect / i_fmt_in_aspect; if( fmt.video.i_height & 1 ) fmt.video.i_height -= 1; i_padd = (i_canvas_height - fmt.video.i_height ) / 2; i_offset = (i_padd & 1); _snprintf( psz_croppadd, 100, "croppadd{paddtop=%d,paddbottom=%d}", i_padd - i_offset, i_padd + i_offset ); // sunqueen modify } } else { /* Crop */ if( i_canvas_aspect < i_fmt_in_aspect ) { /* The canvas has a narrower aspect than the subpicture: * ie, crop the [scaled] subpicture horizontally */ fmt.video.i_width = i_canvas_width * i_fmt_in_aspect / i_canvas_aspect; if( fmt.video.i_width & 1 ) fmt.video.i_width -= 1; i_padd = (fmt.video.i_width - i_canvas_width) / 2; i_offset = (i_padd & 1); _snprintf( psz_croppadd, 100, "croppadd{cropleft=%d,cropright=%d}", i_padd - i_offset, i_padd + i_offset ); // sunqueen modify } else { /* The canvas has a shorter aspect than the subpicture: * ie, crop the [scaled] subpicture vertically */ fmt.video.i_height = i_canvas_height * i_canvas_aspect / i_fmt_in_aspect; if( fmt.video.i_height & 1 ) fmt.video.i_height -= 1; i_padd = (fmt.video.i_height - i_canvas_height) / 2; i_offset = (i_padd & 1); _snprintf( psz_croppadd, 100, "croppadd{croptop=%d,cropbottom=%d}", i_padd - i_offset, i_padd + i_offset ); // sunqueen modify } } /* xxx, should the clean area include the letter-boxing? * probably not, as some codecs can make use of that information * and it should be a scaled version of the input clean area * -- davidf */ fmt.video.i_visible_width = fmt.video.i_width; fmt.video.i_visible_height = fmt.video.i_height; filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &fmt ); /* Append scaling module */ filter_chain_AppendFilter( p_sys->p_chain, NULL, NULL, NULL, NULL ); /* Append padding module */ filter_chain_AppendFromString( p_sys->p_chain, psz_croppadd ); fmt = *filter_chain_GetFmtOut( p_sys->p_chain ); es_format_Copy( &p_filter->fmt_out, &fmt ); p_filter->fmt_out.video.i_sar_num = i_canvas_aspect * p_filter->fmt_out.video.i_height; p_filter->fmt_out.video.i_sar_den = VOUT_ASPECT_FACTOR * p_filter->fmt_out.video.i_width; if( p_filter->fmt_out.video.i_width != i_canvas_width || p_filter->fmt_out.video.i_height != i_canvas_height ) { msg_Warn( p_filter, "Looks like something went wrong. " "Output size is %dx%d while we asked for %dx%d", p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height, i_canvas_width, i_canvas_height ); } p_filter->pf_video_filter = Filter; return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription( p_dec->fmt_in.i_codec ); if( dsc == NULL || dsc->plane_count == 0 ) return VLC_EGENERIC; if( p_dec->fmt_in.video.i_visible_width <= 0 || p_dec->fmt_in.video.i_visible_height <= 0 ) { msg_Err( p_dec, "invalid display size %dx%d", p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ decoder_sys_t *p_sys = calloc(1, sizeof(*p_sys)); if( unlikely(p_sys == NULL) ) return VLC_ENOMEM; if( (int)p_dec->fmt_in.video.i_height < 0 ) { /* Frames are coded from bottom to top */ p_dec->fmt_in.video.i_height = (unsigned int)(-(int)p_dec->fmt_in.video.i_height); p_sys->b_invert = true; } if( !p_dec->fmt_in.video.i_visible_width ) p_dec->fmt_in.video.i_visible_width = p_dec->fmt_in.video.i_width; if( !p_dec->fmt_in.video.i_visible_height ) p_dec->fmt_in.video.i_visible_height = p_dec->fmt_in.video.i_height; es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); date_Init( &p_sys->pts, p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base ); if( p_dec->fmt_out.video.i_frame_rate == 0 || p_dec->fmt_out.video.i_frame_rate_base == 0) { msg_Warn( p_dec, "invalid frame rate %d/%d, using 25 fps instead", p_dec->fmt_out.video.i_frame_rate, p_dec->fmt_out.video.i_frame_rate_base); date_Init( &p_sys->pts, 25, 1 ); } for( unsigned i = 0; i < dsc->plane_count; i++ ) { unsigned pitch = p_dec->fmt_in.video.i_width * dsc->pixel_size * dsc->p[i].w.num / dsc->p[i].w.den; unsigned lines = p_dec->fmt_in.video.i_height * dsc->p[i].h.num / dsc->p[i].h.den; p_sys->pitches[i] = pitch; p_sys->lines[i] = lines; p_sys->size += pitch * lines; } /* Set callbacks */ p_dec->pf_decode_video = (picture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->p_sys = p_sys; return VLC_SUCCESS; }
static int BuildChromaChain( filter_t *p_filter ) { filter_sys_t *p_sys = p_filter->p_sys; es_format_t fmt_mid; /* We have to protect ourself against a too high recursion */ const char *psz_option = MODULE_STRING"-level"; int i_level = 0; for( const config_chain_t *c = p_filter->p_cfg; c != NULL; c = c->p_next) { if( c->psz_name && c->psz_value && !strcmp(c->psz_name, psz_option) ) { i_level = atoi(c->psz_value); if( i_level < 0 || i_level > CHAIN_LEVEL_MAX ) { msg_Err( p_filter, "Too high level of recursion (%d)", i_level ); return VLC_EGENERIC; } break; } } /* */ int i_ret = VLC_EGENERIC; /* */ config_chain_t cfg_level; memset(&cfg_level, 0, sizeof(cfg_level)); cfg_level.psz_name = strdup(psz_option); if( asprintf( &cfg_level.psz_value, "%d", i_level + 1) < 0 ) cfg_level.psz_value = NULL; if( !cfg_level.psz_name || !cfg_level.psz_value ) goto exit; /* Now try chroma format list */ for( int i = 0; pi_allowed_chromas[i]; i++ ) { const vlc_fourcc_t i_chroma = pi_allowed_chromas[i]; if( i_chroma == p_filter->fmt_in.i_codec || i_chroma == p_filter->fmt_out.i_codec ) continue; msg_Dbg( p_filter, "Trying to use chroma %4.4s as middle man", (char*)&i_chroma ); es_format_Copy( &fmt_mid, &p_filter->fmt_in ); fmt_mid.i_codec = fmt_mid.video.i_chroma = i_chroma; fmt_mid.video.i_rmask = 0; fmt_mid.video.i_gmask = 0; fmt_mid.video.i_bmask = 0; video_format_FixRgb(&fmt_mid.video); filter_chain_Reset( p_sys->p_chain, &p_filter->fmt_in, &p_filter->fmt_out ); i_ret = CreateChain( p_sys->p_chain, &fmt_mid, &cfg_level ); es_format_Clean( &fmt_mid ); if( i_ret == VLC_SUCCESS ) break; } exit: free( cfg_level.psz_name ); free( cfg_level.psz_value ); return i_ret; }
/***************************************************************************** * Open: probe the packetizer and return score * When opening after demux, the packetizer is only loaded AFTER the decoder * That means that what you set in fmt_out is ignored by the decoder in this special case *****************************************************************************/ static int Open( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; int i; if( p_dec->fmt_in.i_codec != VLC_CODEC_H264 ) return VLC_EGENERIC; if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1') && p_dec->fmt_in.i_extra < 7 ) return VLC_EGENERIC; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = malloc( sizeof(decoder_sys_t) ) ) == NULL ) { return VLC_ENOMEM; } packetizer_Init( &p_sys->packetizer, p_h264_startcode, sizeof(p_h264_startcode), p_h264_startcode, 1, 5, PacketizeReset, PacketizeParse, PacketizeValidate, p_dec ); p_sys->b_slice = false; p_sys->p_frame = NULL; p_sys->b_frame_sps = false; p_sys->b_frame_pps = false; p_sys->b_header= false; p_sys->b_sps = false; p_sys->b_pps = false; for( i = 0; i < SPS_MAX; i++ ) p_sys->pp_sps[i] = NULL; for( i = 0; i < PPS_MAX; i++ ) p_sys->pp_pps[i] = NULL; p_sys->i_recovery_frames = -1; p_sys->slice.i_nal_type = -1; p_sys->slice.i_nal_ref_idc = -1; p_sys->slice.i_idr_pic_id = -1; p_sys->slice.i_frame_num = -1; p_sys->slice.i_frame_type = 0; p_sys->slice.i_pic_parameter_set_id = -1; p_sys->slice.i_field_pic_flag = 0; p_sys->slice.i_bottom_field_flag = -1; p_sys->slice.i_pic_order_cnt_lsb = -1; p_sys->slice.i_delta_pic_order_cnt_bottom = -1; p_sys->i_frame_dts = VLC_TS_INVALID; p_sys->i_frame_pts = VLC_TS_INVALID; /* Setup properties */ es_format_Copy( &p_dec->fmt_out, &p_dec->fmt_in ); p_dec->fmt_out.i_codec = VLC_CODEC_H264; if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) ) { /* This type of stream is produced by mp4 and matroska * when we want to store it in another streamformat, you need to convert * The fmt_in.p_extra should ALWAYS contain the avcC * The fmt_out.p_extra should contain all the SPS and PPS with 4 byte startcodes */ uint8_t *p = &((uint8_t*)p_dec->fmt_in.p_extra)[4]; int i_sps, i_pps; bool b_dummy; int i; /* Parse avcC */ p_sys->i_avcC_length_size = 1 + ((*p++)&0x03); /* Read SPS */ i_sps = (*p++)&0x1f; for( i = 0; i < i_sps; i++ ) { uint16_t i_length = GetWBE( p ); p += 2; if( i_length > (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p ) { return VLC_EGENERIC; } block_t *p_sps = CreateAnnexbNAL( p_dec, p, i_length ); if( !p_sps ) return VLC_EGENERIC; ParseNALBlock( p_dec, &b_dummy, p_sps ); p += i_length; } /* Read PPS */ i_pps = *p++; for( i = 0; i < i_pps; i++ ) { uint16_t i_length = GetWBE( p ); p += 2; if( i_length > (uint8_t*)p_dec->fmt_in.p_extra + p_dec->fmt_in.i_extra - p ) { return VLC_EGENERIC; } block_t *p_pps = CreateAnnexbNAL( p_dec, p, i_length ); if( !p_pps ) return VLC_EGENERIC; ParseNALBlock( p_dec, &b_dummy, p_pps ); p += i_length; } msg_Dbg( p_dec, "avcC length size=%d, sps=%d, pps=%d", p_sys->i_avcC_length_size, i_sps, i_pps ); if( !p_sys->b_sps || !p_sys->b_pps ) return VLC_EGENERIC; /* FIXME: FFMPEG isn't happy at all if you leave this */ if( p_dec->fmt_out.i_extra > 0 ) free( p_dec->fmt_out.p_extra ); p_dec->fmt_out.i_extra = 0; p_dec->fmt_out.p_extra = NULL; /* Set the new extradata */ for( i = 0; i < SPS_MAX; i++ ) { if( p_sys->pp_sps[i] ) p_dec->fmt_out.i_extra += p_sys->pp_sps[i]->i_buffer; } for( i = 0; i < PPS_MAX; i++ ) { if( p_sys->pp_pps[i] ) p_dec->fmt_out.i_extra += p_sys->pp_pps[i]->i_buffer; } p_dec->fmt_out.p_extra = malloc( p_dec->fmt_out.i_extra ); if( p_dec->fmt_out.p_extra ) { uint8_t *p_dst = p_dec->fmt_out.p_extra; for( i = 0; i < SPS_MAX; i++ ) { if( p_sys->pp_sps[i] ) { memcpy( p_dst, p_sys->pp_sps[i]->p_buffer, p_sys->pp_sps[i]->i_buffer ); p_dst += p_sys->pp_sps[i]->i_buffer; } } for( i = 0; i < PPS_MAX; i++ ) { if( p_sys->pp_pps[i] ) { memcpy( p_dst, p_sys->pp_pps[i]->p_buffer, p_sys->pp_pps[i]->i_buffer ); p_dst += p_sys->pp_pps[i]->i_buffer; } } p_sys->b_header = true; } else { p_dec->fmt_out.i_extra = 0; } /* Set callback */ p_dec->pf_packetize = PacketizeAVC1; /* TODO CC ? */ } else { /* This type of stream contains data with 3 of 4 byte startcodes * The fmt_in.p_extra MAY contain SPS/PPS with 4 byte startcodes * The fmt_out.p_extra should be the same */ /* Set callback */ p_dec->pf_packetize = Packetize; p_dec->pf_get_cc = GetCc; /* */ p_sys->i_cc_pts = VLC_TS_INVALID; p_sys->i_cc_dts = VLC_TS_INVALID; p_sys->i_cc_flags = 0; cc_Init( &p_sys->cc ); cc_Init( &p_sys->cc_next ); /* */ if( p_dec->fmt_in.i_extra > 0 ) packetizer_Header( &p_sys->packetizer, p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra ); } return VLC_SUCCESS; }
/* Helpers */ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain, const char *psz_name, config_chain_t *p_cfg, const es_format_t *p_fmt_in, const es_format_t *p_fmt_out ) { chained_filter_t *p_chained = vlc_custom_create( p_chain->p_this, sizeof(*p_chained), "filter" ); filter_t *p_filter = &p_chained->filter; if( !p_filter ) return NULL; if( !p_fmt_in ) { if( p_chain->last != NULL ) p_fmt_in = &p_chain->last->filter.fmt_out; else p_fmt_in = &p_chain->fmt_in; } if( !p_fmt_out ) { p_fmt_out = &p_chain->fmt_out; } es_format_Copy( &p_filter->fmt_in, p_fmt_in ); es_format_Copy( &p_filter->fmt_out, p_fmt_out ); p_filter->p_cfg = p_cfg; p_filter->b_allow_fmt_out_change = p_chain->b_allow_fmt_out_change; p_filter->p_module = module_need( p_filter, p_chain->psz_capability, psz_name, psz_name != NULL ); if( !p_filter->p_module ) goto error; if( p_filter->b_allow_fmt_out_change ) { es_format_Clean( &p_chain->fmt_out ); es_format_Copy( &p_chain->fmt_out, &p_filter->fmt_out ); } if( AllocatorInit( &p_chain->allocator, p_chained ) ) goto error; if( p_chain->last == NULL ) { assert( p_chain->first == NULL ); p_chain->first = p_chained; } else p_chain->last->next = p_chained; p_chained->prev = p_chain->last; p_chain->last = p_chained; p_chained->next = NULL; p_chain->length++; vlc_mouse_t *p_mouse = malloc( sizeof(*p_mouse) ); if( p_mouse ) vlc_mouse_Init( p_mouse ); p_chained->mouse = p_mouse; p_chained->pending = NULL; msg_Dbg( p_chain->p_this, "Filter '%s' (%p) appended to chain", psz_name ? psz_name : module_get_name(p_filter->p_module, false), p_filter ); return p_filter; error: if( psz_name ) msg_Err( p_chain->p_this, "Failed to create %s '%s'", p_chain->psz_capability, psz_name ); else msg_Err( p_chain->p_this, "Failed to create %s", p_chain->psz_capability ); if( p_filter->p_module ) module_unneed( p_filter, p_filter->p_module ); es_format_Clean( &p_filter->fmt_in ); es_format_Clean( &p_filter->fmt_out ); vlc_object_release( p_filter ); return NULL; }