📄 dmo.c
字号:
/* No output generated */#ifdef DMO_DEBUG msg_Dbg( p_dec, "ProcessInput(): no output generated" );#endif return NULL; } else if( i_result == DMO_E_NOTACCEPTING ) { /* Need to call ProcessOutput */ msg_Dbg( p_dec, "ProcessInput(): not accepting" ); } else if( i_result != S_OK ) { msg_Dbg( p_dec, "ProcessInput(): failed" ); return NULL; } else { //msg_Dbg( p_dec, "ProcessInput(): successful" ); *pp_block = 0; } } else if( p_block && !p_block->i_buffer ) { block_Release( p_block ); *pp_block = 0; } /* Get output from the DMO */ block_out.p_buffer = p_sys->p_buffer; block_out.i_buffer = 0; p_out = CMediaBufferCreate( &block_out, p_sys->i_min_output, VLC_FALSE ); memset( &db, 0, sizeof(db) ); db.pBuffer = (IMediaBuffer *)p_out; i_result = p_sys->p_dmo->vt->ProcessOutput( p_sys->p_dmo, DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER, 1, &db, &i_status ); if( i_result != S_OK ) { if( i_result != S_FALSE ) msg_Dbg( p_dec, "ProcessOutput(): failed" );#if DMO_DEBUG else msg_Dbg( p_dec, "ProcessOutput(): no output" );#endif p_out->vt->Release( (IUnknown *)p_out ); return NULL; }#if DMO_DEBUG msg_Dbg( p_dec, "ProcessOutput(): success" );#endif if( !block_out.i_buffer ) {#if DMO_DEBUG msg_Dbg( p_dec, "ProcessOutput(): no output (i_buffer_out == 0)" );#endif p_out->vt->Release( (IUnknown *)p_out ); return NULL; } if( p_dec->fmt_out.i_cat == VIDEO_ES ) { /* Get a new picture */ picture_t *p_pic = p_dec->pf_vout_buffer_new( p_dec ); if( !p_pic ) return NULL; CopyPicture( p_dec, p_pic, block_out.p_buffer ); /* Date management */ p_pic->date = date_Get( &p_sys->end_date ); date_Increment( &p_sys->end_date, 1 ); p_out->vt->Release( (IUnknown *)p_out ); return p_pic; } else { aout_buffer_t *p_aout_buffer; int i_samples = block_out.i_buffer / ( p_dec->fmt_out.audio.i_bitspersample * p_dec->fmt_out.audio.i_channels / 8 ); p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec, i_samples ); memcpy( p_aout_buffer->p_buffer, block_out.p_buffer, block_out.i_buffer ); /* Date management */ p_aout_buffer->start_date = date_Get( &p_sys->end_date ); p_aout_buffer->end_date = date_Increment( &p_sys->end_date, i_samples ); p_out->vt->Release( (IUnknown *)p_out ); return p_aout_buffer; } return NULL;}static void CopyPicture( decoder_t *p_dec, picture_t *p_pic, uint8_t *p_in ){ int i_plane, i_line, i_width, i_dst_stride; uint8_t *p_dst, *p_src = p_in; p_dst = p_pic->p[1].p_pixels; p_pic->p[1].p_pixels = p_pic->p[2].p_pixels; p_pic->p[2].p_pixels = p_dst; for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { p_dst = p_pic->p[i_plane].p_pixels; i_width = p_pic->p[i_plane].i_visible_pitch; i_dst_stride = p_pic->p[i_plane].i_pitch; for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ ) { p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_width ); p_src += i_width; p_dst += i_dst_stride; } } p_dst = p_pic->p[1].p_pixels; p_pic->p[1].p_pixels = p_pic->p[2].p_pixels; p_pic->p[2].p_pixels = p_dst;}/**************************************************************************** * Encoder descriptor declaration ****************************************************************************/struct encoder_sys_t{ HINSTANCE hmsdmo_dll; IMediaObject *p_dmo; int i_min_output; date_t end_date;#ifdef LOADER ldt_fs_t *ldt_fs;#endif};/***************************************************************************** * EncoderOpen: open dmo codec *****************************************************************************/static int EncoderOpen( vlc_object_t *p_this ){ encoder_t *p_enc = (encoder_t*)p_this;#ifndef LOADER int i_ret = EncOpen( p_this ); if( i_ret != VLC_SUCCESS ) return i_ret;#else /* We can't open it now, because of ldt_keeper or something * Open/Encode/Close has to be done in the same thread */ int i; /* Probe if we support it */ for( i = 0; encoders_table[i].i_fourcc != 0; i++ ) { if( encoders_table[i].i_fourcc == p_enc->fmt_out.i_codec ) { msg_Dbg( p_enc, "DMO codec for %4.4s may work with dll=%s", (char*)&p_enc->fmt_out.i_codec, encoders_table[i].psz_dll ); break; } } p_enc->p_sys = NULL; if( !encoders_table[i].i_fourcc ) return VLC_EGENERIC;#endif /* LOADER */ /* Set callbacks */ p_enc->pf_encode_video = (block_t *(*)(encoder_t *, picture_t *)) EncodeBlock; p_enc->pf_encode_audio = (block_t *(*)(encoder_t *, aout_buffer_t *)) EncodeBlock; return VLC_SUCCESS;}/***************************************************************************** * EncoderSetVideoType: configures the input and output types of the dmo *****************************************************************************/static int EncoderSetVideoType( encoder_t *p_enc, IMediaObject *p_dmo ){ int i, i_selected, i_err; DMO_MEDIA_TYPE dmo_type; VIDEOINFOHEADER vih, *p_vih; BITMAPINFOHEADER *p_bih; /* FIXME */ p_enc->fmt_in.video.i_bits_per_pixel = p_enc->fmt_out.video.i_bits_per_pixel = 12; /* Enumerate input format (for debug output) */ i = 0; while( !p_dmo->vt->GetInputType( p_dmo, 0, i++, &dmo_type ) ) { p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat; msg_Dbg( p_enc, "available input chroma: %4.4s", (char *)&dmo_type.subtype.Data1 ); if( !memcmp( &dmo_type.subtype, &MEDIASUBTYPE_RGB565, 16 ) ) msg_Dbg( p_enc, "-> MEDIASUBTYPE_RGB565" ); if( !memcmp( &dmo_type.subtype, &MEDIASUBTYPE_RGB24, 16 ) ) msg_Dbg( p_enc, "-> MEDIASUBTYPE_RGB24" ); DMOFreeMediaType( &dmo_type ); } /* Setup input format */ memset( &dmo_type, 0, sizeof(dmo_type) ); dmo_type.pUnk = 0; memset( &vih, 0, sizeof(VIDEOINFOHEADER) ); p_bih = &vih.bmiHeader; p_bih->biCompression = VLC_FOURCC('I','4','2','0'); p_bih->biWidth = p_enc->fmt_in.video.i_width; p_bih->biHeight = p_enc->fmt_in.video.i_height; p_bih->biBitCount = p_enc->fmt_in.video.i_bits_per_pixel; p_bih->biSizeImage = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * p_enc->fmt_in.video.i_bits_per_pixel /8; p_bih->biPlanes = 3; p_bih->biSize = sizeof(BITMAPINFOHEADER); vih.rcSource.left = vih.rcSource.top = 0; vih.rcSource.right = p_enc->fmt_in.video.i_width; vih.rcSource.bottom = p_enc->fmt_in.video.i_height; vih.rcTarget = vih.rcSource; vih.AvgTimePerFrame = I64C(10000000) / 25; //FIXME dmo_type.majortype = MEDIATYPE_Video; //dmo_type.subtype = MEDIASUBTYPE_RGB24; dmo_type.subtype = MEDIASUBTYPE_I420; //dmo_type.subtype.Data1 = p_bih->biCompression; dmo_type.formattype = FORMAT_VideoInfo; dmo_type.bFixedSizeSamples = TRUE; dmo_type.bTemporalCompression = FALSE; dmo_type.lSampleSize = p_bih->biSizeImage; dmo_type.cbFormat = sizeof(VIDEOINFOHEADER); dmo_type.pbFormat = (char *)&vih; if( ( i_err = p_dmo->vt->SetInputType( p_dmo, 0, &dmo_type, 0 ) ) ) { msg_Err( p_enc, "can't set DMO input type: %x", i_err ); return VLC_EGENERIC; } msg_Dbg( p_enc, "successfully set input type" ); /* Setup output format */ memset( &dmo_type, 0, sizeof(dmo_type) ); dmo_type.pUnk = 0; /* Enumerate output types */ i = 0, i_selected = -1; while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &dmo_type ) ) { p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat; msg_Dbg( p_enc, "available output codec: %4.4s", (char *)&dmo_type.subtype.Data1 ); if( p_vih->bmiHeader.biCompression == p_enc->fmt_out.i_codec ) i_selected = i - 1; DMOFreeMediaType( &dmo_type ); } if( i_selected < 0 ) { msg_Err( p_enc, "couldn't find codec: %4.4s", (char *)&p_enc->fmt_out.i_codec ); return VLC_EGENERIC; } p_dmo->vt->GetOutputType( p_dmo, 0, i_selected, &dmo_type ); ((VIDEOINFOHEADER *)dmo_type.pbFormat)->dwBitRate = p_enc->fmt_out.i_bitrate; /* Get the private data for the codec */ while( 1 ) { IWMCodecPrivateData *p_privdata; VIDEOINFOHEADER *p_vih; uint8_t *p_data = 0; uint32_t i_data = 0, i_vih; i_err = p_dmo->vt->QueryInterface( (IUnknown *)p_dmo, &IID_IWMCodecPrivateData, (void **)&p_privdata ); if( i_err ) break; i_err = p_privdata->vt->SetPartialOutputType( p_privdata, &dmo_type ); if( i_err ) { msg_Err( p_enc, "SetPartialOutputType() failed" ); p_privdata->vt->Release( (IUnknown *)p_privdata ); break; } i_err = p_privdata->vt->GetPrivateData( p_privdata, NULL, &i_data ); if( i_err ) { msg_Err( p_enc, "GetPrivateData() failed" ); p_privdata->vt->Release( (IUnknown *)p_privdata ); break; } p_data = malloc( i_data ); i_err = p_privdata->vt->GetPrivateData( p_privdata, p_data, &i_data ); /* Update the media type with the private data */ i_vih = dmo_type.cbFormat + i_data; p_vih = CoTaskMemAlloc( i_vih ); memcpy( p_vih, dmo_type.pbFormat, dmo_type.cbFormat ); memcpy( ((uint8_t *)p_vih) + dmo_type.cbFormat, p_data, i_data ); DMOFreeMediaType( &dmo_type ); dmo_type.pbFormat = p_vih; dmo_type.cbFormat = i_vih; msg_Dbg( p_enc, "found extra data: %i", i_data ); p_enc->fmt_out.i_extra = i_data; p_enc->fmt_out.p_extra = p_data; break; } i_err = p_dmo->vt->SetOutputType( p_dmo, 0, &dmo_type, 0 ); p_vih = (VIDEOINFOHEADER *)dmo_type.pbFormat; p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0'); DMOFreeMediaType( &dmo_type ); if( i_err ) { msg_Err( p_enc, "can't set DMO output type: %i", i_err ); return VLC_EGENERIC; } msg_Dbg( p_enc, "successfully set output type" ); return VLC_SUCCESS;}/***************************************************************************** * EncoderSetAudioType: configures the input and output types of the dmo *****************************************************************************/static int EncoderSetAudioType( encoder_t *p_enc, IMediaObject *p_dmo ){ int i, i_selected, i_err; unsigned int i_last_byterate; uint16_t i_tag; DMO_MEDIA_TYPE dmo_type; WAVEFORMATEX *p_wf; /* Setup the format structure */ fourcc_to_wf_tag( p_enc->fmt_out.i_codec, &i_tag ); if( i_tag == 0 ) return VLC_EGENERIC; p_enc->fmt_in.i_codec = AOUT_FMT_S16_NE; p_enc->fmt_in.audio.i_bitspersample = 16; /* We first need to choose an output type from the predefined * list of choices (we cycle through the list to select the best match) */ i = 0; i_selected = -1; i_last_byterate = 0; while( !p_dmo->vt->GetOutputType( p_dmo, 0, i++, &dmo_type ) ) { p_wf = (WAVEFORMATEX *)dmo_type.pbFormat; msg_Dbg( p_enc, "available format :%i, sample rate: %i, channels: %i, " "bits per sample: %i, bitrate: %i, blockalign: %i", (int) p_wf->wFormatTag, (int)p_wf->nSamplesPerSec, (int)p_wf->nChannels, (int)p_wf->wBitsPerSample, (int)p_wf->nAvgBytesPerSec * 8, (int)p_wf->nBlockAlign ); if( p_wf->wFormatTag == i_tag && p_wf->nSamplesPerSec == p_enc->fmt_in.audio.i_rate && p_wf->nChannels == p_enc->fmt_in.audio.i_channels && p_wf->wBitsPerSample == p_enc->fmt_in.audio.i_bitspersample ) { if( (int)p_wf->nAvgBytesPerSec <
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -