public bool Transcode(TranscodeInfo info, VideoFormat format, Quality quality, Standard standard) { try { if (!Supports(format)) return false; string ext = System.IO.Path.GetExtension(info.file); if (ext.ToLower() != ".ts" && ext.ToLower() != ".mpg") { Log.Info("TSReader2WMV: wrong file format"); return false; } Log.Info("TSReader2WMV: create graph"); graphBuilder = (IGraphBuilder)new FilterGraph(); _rotEntry = new DsROTEntry((IFilterGraph)graphBuilder); Log.Info("TSReader2WMV: add filesource"); TsReader reader = new TsReader(); tsreaderSource = (IBaseFilter)reader; //ITSReader ireader = (ITSReader)reader; //ireader.SetTsReaderCallback(this); //ireader.SetRequestAudioChangeCallback(this); IBaseFilter filter = (IBaseFilter)tsreaderSource; graphBuilder.AddFilter(filter, "TSReader Source"); IFileSourceFilter fileSource = (IFileSourceFilter)tsreaderSource; Log.Info("TSReader2WMV: load file:{0}", info.file); int hr = fileSource.Load(info.file, null); //add audio/video codecs string strVideoCodec = ""; string strH264VideoCodec = ""; string strAudioCodec = ""; string strAACAudioCodec = ""; using (MediaPortal.Profile.Settings xmlreader = new MediaPortal.Profile.MPSettings()) { strVideoCodec = xmlreader.GetValueAsString("mytv", "videocodec", ""); strAudioCodec = xmlreader.GetValueAsString("mytv", "audiocodec", ""); strAACAudioCodec = xmlreader.GetValueAsString("mytv", "aacaudiocodec", ""); strH264VideoCodec = xmlreader.GetValueAsString("mytv", "h264videocodec", ""); } //Find the type of decoder required for the output video & audio pins on TSReader. Log.Info("TSReader2WMV: find tsreader compatible audio/video decoders"); IPin pinOut0, pinOut1; IPin pinIn0, pinIn1; pinOut0 = DsFindPin.ByDirection((IBaseFilter)tsreaderSource, PinDirection.Output, 0); //audio pinOut1 = DsFindPin.ByDirection((IBaseFilter)tsreaderSource, PinDirection.Output, 1); //video if (pinOut0 == null || pinOut1 == null) { Log.Error("TSReader2WMV: FAILED: unable to get output pins of tsreader"); Cleanup(); return false; } bool usingAAC = false; IEnumMediaTypes enumMediaTypes; hr = pinOut0.EnumMediaTypes(out enumMediaTypes); while (true) { AMMediaType[] mediaTypes = new AMMediaType[1]; int typesFetched; hr = enumMediaTypes.Next(1, mediaTypes, out typesFetched); if (hr != 0 || typesFetched == 0) break; if (mediaTypes[0].majorType == MediaType.Audio && mediaTypes[0].subType == MediaSubType.LATMAAC) { Log.Info("TSReader2WMV: found LATM AAC audio out pin on tsreader"); usingAAC = true; } } bool usingH264 = false; hr = pinOut1.EnumMediaTypes(out enumMediaTypes); while (true) { AMMediaType[] mediaTypes = new AMMediaType[1]; int typesFetched; hr = enumMediaTypes.Next(1, mediaTypes, out typesFetched); if (hr != 0 || typesFetched == 0) break; if (mediaTypes[0].majorType == MediaType.Video && mediaTypes[0].subType == AVC1) { Log.Info("TSReader2WMV: found H.264 video out pin on tsreader"); usingH264 = true; } } //Add the type of decoder required for the output video & audio pins on TSReader. Log.Info("TSReader2WMV: add audio/video decoders to graph"); if (usingH264 == false) { Log.Info("TSReader2WMV: add mpeg2 video decoder:{0}", strVideoCodec); VideoCodec = DirectShowUtil.AddFilterToGraph(graphBuilder, strVideoCodec); if (VideoCodec == null) { Log.Error("TSReader2WMV: unable to add mpeg2 video decoder"); Cleanup(); return false; } } else { Log.Info("TSReader2WMV: add h264 video codec:{0}", strH264VideoCodec); VideoCodec = DirectShowUtil.AddFilterToGraph(graphBuilder, strH264VideoCodec); if (VideoCodec == null) { Log.Error("TSReader2WMV: FAILED:unable to add h264 video codec"); Cleanup(); return false; } } if (usingAAC == false) { Log.Info("TSReader2WMV: add mpeg2 audio codec:{0}", strAudioCodec); AudioCodec = DirectShowUtil.AddFilterToGraph(graphBuilder, strAudioCodec); if (AudioCodec == null) { Log.Error("TSReader2WMV: FAILED:unable to add mpeg2 audio codec"); Cleanup(); return false; } } else { Log.Info("TSReader2WMV: add aac audio codec:{0}", strAACAudioCodec); AudioCodec = DirectShowUtil.AddFilterToGraph(graphBuilder, strAACAudioCodec); if (AudioCodec == null) { Log.Error("TSReader2WMV: FAILED:unable to add aac audio codec"); Cleanup(); return false; } } Log.Info("TSReader2WMV: connect tsreader->audio/video decoders"); //connect output #0 (audio) of tsreader->audio decoder input pin 0 //connect output #1 (video) of tsreader->video decoder input pin 0 pinIn0 = DsFindPin.ByDirection(AudioCodec, PinDirection.Input, 0); //audio pinIn1 = DsFindPin.ByDirection(VideoCodec, PinDirection.Input, 0); //video if (pinIn0 == null || pinIn1 == null) { Log.Error("TSReader2WMV: FAILED: unable to get pins of video/audio codecs"); Cleanup(); return false; } hr = graphBuilder.Connect(pinOut0, pinIn0); if (hr != 0) { Log.Error("TSReader2WMV: FAILED: unable to connect audio pins :0x{0:X}", hr); Cleanup(); return false; } hr = graphBuilder.Connect(pinOut1, pinIn1); if (hr != 0) { Log.Error("TSReader2WMV: FAILED: unable to connect video pins :0x{0:X}", hr); Cleanup(); return false; } string outputFilename = System.IO.Path.ChangeExtension(info.file, ".wmv"); if (!AddWmAsfWriter(outputFilename, quality, standard)) return false; Log.Info("TSReader2WMV: start pre-run"); mediaControl = graphBuilder as IMediaControl; mediaSeeking = tsreaderSource as IMediaSeeking; mediaEvt = graphBuilder as IMediaEventEx; mediaPos = graphBuilder as IMediaPosition; //get file duration long lTime = 5 * 60 * 60; lTime *= 10000000; long pStop = 0; hr = mediaSeeking.SetPositions(new DsLong(lTime), AMSeekingSeekingFlags.AbsolutePositioning, new DsLong(pStop), AMSeekingSeekingFlags.NoPositioning); if (hr == 0) { long lStreamPos; mediaSeeking.GetCurrentPosition(out lStreamPos); // stream position m_dDuration = lStreamPos; lTime = 0; mediaSeeking.SetPositions(new DsLong(lTime), AMSeekingSeekingFlags.AbsolutePositioning, new DsLong(pStop), AMSeekingSeekingFlags.NoPositioning); } double duration = m_dDuration / 10000000d; Log.Info("TSReader2WMV: movie duration:{0}", Util.Utils.SecondsToHMSString((int)duration)); hr = mediaControl.Run(); if (hr != 0) { Log.Error("TSReader2WMV: FAILED: unable to start graph :0x{0:X}", hr); Cleanup(); return false; } int maxCount = 20; while (true) { long lCurrent; mediaSeeking.GetCurrentPosition(out lCurrent); double dpos = (double)lCurrent; dpos /= 10000000d; System.Threading.Thread.Sleep(100); if (dpos >= 2.0d) break; maxCount--; if (maxCount <= 0) break; } Log.Info("TSReader2WMV: pre-run done"); Log.Info("TSReader2WMV: Get duration of movie"); mediaControl.Stop(); FilterState state; mediaControl.GetState(500, out state); GC.Collect(); GC.Collect(); GC.Collect(); GC.WaitForPendingFinalizers(); Log.Info("TSReader2WMV: reconnect mpeg2 video codec->ASF WM Writer"); graphBuilder.RemoveFilter(fileWriterbase); if (!AddWmAsfWriter(outputFilename, quality, standard)) return false; Log.Info("TSReader2WMV: Start transcoding"); hr = mediaControl.Run(); if (hr != 0) { Log.Error("TSReader2WMV:FAILED:unable to start graph :0x{0:X}", hr); Cleanup(); return false; } } catch (Exception e) { // TODO: Handle exceptions. Log.Error("unable to transcode file:{0} message:{1}", info.file, e.Message); return false; } return true; }
private bool AddWmAsfWriter(string fileName, Quality quality, Standard standard) { //add asf file writer IPin pinOut0, pinOut1; IPin pinIn0, pinIn1; Log.Info("TSReader2WMV: add WM ASF Writer to graph"); string monikerAsfWriter = @"@device:sw:{083863F1-70DE-11D0-BD40-00A0C911CE86}\{7C23220E-55BB-11D3-8B16-00C04FB6BD3D}"; fileWriterbase = Marshal.BindToMoniker(monikerAsfWriter) as IBaseFilter; if (fileWriterbase == null) { Log.Error("TSReader2WMV:FAILED:Unable to create ASF WM Writer"); Cleanup(); return false; } int hr = graphBuilder.AddFilter(fileWriterbase, "WM ASF Writer"); if (hr != 0) { Log.Error("TSReader2WMV:FAILED:Add ASF WM Writer to filtergraph :0x{0:X}", hr); Cleanup(); return false; } IFileSinkFilter2 fileWriterFilter = fileWriterbase as IFileSinkFilter2; if (fileWriterFilter == null) { Log.Error("DVR2XVID:FAILED:Add unable to get IFileSinkFilter for filewriter"); Cleanup(); return false; } hr = fileWriterFilter.SetFileName(fileName, null); hr = fileWriterFilter.SetMode(AMFileSinkFlags.OverWrite); Log.Info("TSReader2WMV: connect audio/video codecs outputs -> ASF WM Writer"); //connect output #0 of videocodec->asf writer pin 1 //connect output #0 of audiocodec->asf writer pin 0 pinOut0 = DsFindPin.ByDirection((IBaseFilter)AudioCodec, PinDirection.Output, 0); pinOut1 = DsFindPin.ByDirection((IBaseFilter)VideoCodec, PinDirection.Output, 0); if (pinOut0 == null || pinOut1 == null) { Log.Error("TSReader2WMV:FAILED:unable to get outpins of video codec"); Cleanup(); return false; } pinIn0 = DsFindPin.ByDirection(fileWriterbase, PinDirection.Input, 0); if (pinIn0 == null) { Log.Error("TSReader2WMV:FAILED:unable to get pins of asf wm writer"); Cleanup(); return false; } hr = graphBuilder.Connect(pinOut0, pinIn0); if (hr != 0) { Log.Error("TSReader2WMV:FAILED:unable to connect audio pins :0x{0:X}", hr); Cleanup(); return false; } pinIn1 = DsFindPin.ByDirection(fileWriterbase, PinDirection.Input, 1); if (pinIn1 == null) { Log.Error("TSReader2WMV:FAILED:unable to get pins of asf wm writer"); Cleanup(); return false; } hr = graphBuilder.Connect(pinOut1, pinIn1); if (hr != 0) { Log.Error("TSReader2WMV:FAILED:unable to connect video pins :0x{0:X}", hr); Cleanup(); return false; } IConfigAsfWriter config = fileWriterbase as IConfigAsfWriter; IWMProfileManager profileManager = null; IWMProfileManager2 profileManager2 = null; IWMProfile profile = null; hr = WMLib.WMCreateProfileManager(out profileManager); string strprofileType = ""; switch (quality) { case Quality.HiDef: //hr = WMLib.WMCreateProfileManager(out profileManager); if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHiDef-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHiDef-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHiDef-PAL.prx"); } Log.Info("TSReader2WMV: set WMV HiDef quality profile {0}", strprofileType); break; case Quality.VeryHigh: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPVeryHigh-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPVeryHigh-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPVeryHigh-PAL.prx"); } Log.Info("TSReader2WMV: set WMV Very High quality profile {0}", strprofileType); break; case Quality.High: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHigh-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHigh-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHigh-PAL.prx"); } Log.Info("TSReader2WMV: set WMV High quality profile {0}", strprofileType); break; case Quality.Medium: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPMedium-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPMedium-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPMedium-PAL.prx"); } Log.Info("TSReader2WMV: set WMV Medium quality profile {0}", strprofileType); break; case Quality.Low: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPLow-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPLow-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPLow-PAL.prx"); } Log.Info("TSReader2WMV: set WMV Low quality profile {0}", strprofileType); break; case Quality.Portable: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPPortable-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPPortable-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPPortable-PAL.prx"); } Log.Info("TSReader2WMV: set WMV Portable quality profile {0}", strprofileType); break; case Quality.Custom: //load custom profile string customBitrate = ""; //Adjust the parameters to suit the custom settings the user has selected. switch (bitrate) { case 0: customBitrate = "100Kbs"; break; case 1: customBitrate = "256Kbs"; break; case 2: customBitrate = "384Kbs"; break; case 3: customBitrate = "768Kbs"; break; case 4: customBitrate = "1536Kbs"; break; case 5: customBitrate = "3072Kbs"; break; case 6: customBitrate = "5376Kbs"; break; } Log.Info("TSReader2WMV: custom bitrate = {0}", customBitrate); //TODO: get fps values & frame size //TODO: adjust settings required //Call the SetCutomPorfile method to load the custom profile, adjust it's params from user settings & then save it. //SetCutomProfile(videoBitrate, audioBitrate, videoHeight, videoWidth, videoFps); //based on user inputs //We then reload it after as per other quality settings / profiles. strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPCustom.prx"); Log.Info("TSReader2WMV: set WMV Custom quality profile {0}", strprofileType); break; } //Loads profile from the above quality selection. using (StreamReader prx = new StreamReader(strprofileType)) { String profileContents = prx.ReadToEnd(); profileManager2 = profileManager as IWMProfileManager2; hr = profileManager2.LoadProfileByData(profileContents, out profile); } if (hr != 0) { Log.Info("TSReader2WMV: get WMV profile - FAILED! {0}", hr); Cleanup(); return false; } Log.Info("TSReader2WMV: load profile - SUCCESS!"); //configures the WM ASF Writer to the chosen profile hr = config.ConfigureFilterUsingProfile(profile); if (hr != 0) { Log.Info("TSReader2WMV: configure profile - FAILED! {0}", hr); Cleanup(); return false; } Log.Info("TSReader2WMV: configure profile - SUCCESS!"); //TODO: Add DB recording information into WMV. //Release resorces if (profile != null) { Marshal.ReleaseComObject(profile); profile = null; } if (profileManager != null) { Marshal.ReleaseComObject(profileManager); profileManager = null; } return true; }
public bool Transcode(TranscodeInfo info, VideoFormat format, Quality quality, Standard standard) { try { if (!Supports(format)) return false; string ext = System.IO.Path.GetExtension(info.file); if (ext.ToLowerInvariant() != ".dvr-ms" && ext.ToLowerInvariant() != ".sbe") { Log.Info("DVRMS2WMV: wrong file format"); return false; } Log.Info("DVRMS2WMV: create graph"); graphBuilder = (IGraphBuilder)new FilterGraph(); _rotEntry = new DsROTEntry((IFilterGraph)graphBuilder); Log.Info("DVRMS2WMV: add streambuffersource"); bufferSource = (IStreamBufferSource)new StreamBufferSource(); IBaseFilter filter = (IBaseFilter)bufferSource; graphBuilder.AddFilter(filter, "SBE SOURCE"); Log.Info("DVRMS2WMV: load file:{0}", info.file); IFileSourceFilter fileSource = (IFileSourceFilter)bufferSource; int hr = fileSource.Load(info.file, null); //add mpeg2 audio/video codecs string strVideoCodec = ""; string strAudioCodec = ""; using (MediaPortal.Profile.Settings xmlreader = new MediaPortal.Profile.MPSettings()) { strVideoCodec = xmlreader.GetValueAsString("mytv", "videocodec", "MPC - MPEG-2 Video Decoder (Gabest)"); strAudioCodec = xmlreader.GetValueAsString("mytv", "audiocodec", "MPC - MPA Decoder Filter"); } Log.Info("DVRMS2WMV: add mpeg2 video codec:{0}", strVideoCodec); Mpeg2VideoCodec = DirectShowUtil.AddFilterToGraph(graphBuilder, strVideoCodec); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:Add mpeg2 video to filtergraph :0x{0:X}", hr); Cleanup(); return false; } Log.Info("DVRMS2WMV: add mpeg2 audio codec:{0}", strAudioCodec); Mpeg2AudioCodec = DirectShowUtil.AddFilterToGraph(graphBuilder, strAudioCodec); if (Mpeg2AudioCodec == null) { Log.Error("DVRMS2WMV:FAILED:unable to add mpeg2 audio codec"); Cleanup(); return false; } Log.Info("DVRMS2WMV: connect streambufer source->mpeg audio/video decoders"); //connect output #0 of streambuffer source->mpeg2 audio codec pin 1 //connect output #1 of streambuffer source->mpeg2 video codec pin 1 IPin pinOut0, pinOut1; IPin pinIn0, pinIn1; pinOut0 = DsFindPin.ByDirection((IBaseFilter)bufferSource, PinDirection.Output, 0); //audio pinOut1 = DsFindPin.ByDirection((IBaseFilter)bufferSource, PinDirection.Output, 1); //video if (pinOut0 == null || pinOut1 == null) { Log.Error("DVRMS2WMV:FAILED:unable to get pins of source"); Cleanup(); return false; } pinIn0 = DsFindPin.ByDirection(Mpeg2VideoCodec, PinDirection.Input, 0); //video pinIn1 = DsFindPin.ByDirection(Mpeg2AudioCodec, PinDirection.Input, 0); //audio if (pinIn0 == null || pinIn1 == null) { Log.Error("DVRMS2WMV:FAILED:unable to get pins of mpeg2 video/audio codec"); Cleanup(); return false; } hr = graphBuilder.Connect(pinOut0, pinIn1); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:unable to connect audio pins :0x{0:X}", hr); Cleanup(); return false; } hr = graphBuilder.Connect(pinOut1, pinIn0); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:unable to connect video pins :0x{0:X}", hr); Cleanup(); return false; } string outputFilename = System.IO.Path.ChangeExtension(info.file, ".wmv"); if (!AddWmAsfWriter(outputFilename, quality, standard)) return false; Log.Info("DVRMS2WMV: start pre-run"); mediaControl = graphBuilder as IMediaControl; mediaSeeking = bufferSource as IStreamBufferMediaSeeking; mediaEvt = graphBuilder as IMediaEventEx; mediaPos = graphBuilder as IMediaPosition; //get file duration long lTime = 5 * 60 * 60; lTime *= 10000000; long pStop = 0; hr = mediaSeeking.SetPositions(new DsLong(lTime), AMSeekingSeekingFlags.AbsolutePositioning, new DsLong(pStop), AMSeekingSeekingFlags.NoPositioning); if (hr == 0) { long lStreamPos; mediaSeeking.GetCurrentPosition(out lStreamPos); // stream position m_dDuration = lStreamPos; lTime = 0; mediaSeeking.SetPositions(new DsLong(lTime), AMSeekingSeekingFlags.AbsolutePositioning, new DsLong(pStop), AMSeekingSeekingFlags.NoPositioning); } double duration = m_dDuration / 10000000d; Log.Info("DVRMS2WMV: movie duration:{0}", Util.Utils.SecondsToHMSString((int)duration)); hr = mediaControl.Run(); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:unable to start graph :0x{0:X}", hr); Cleanup(); return false; } int maxCount = 20; while (true) { long lCurrent; mediaSeeking.GetCurrentPosition(out lCurrent); double dpos = (double)lCurrent; dpos /= 10000000d; System.Threading.Thread.Sleep(100); if (dpos >= 2.0d) break; maxCount--; if (maxCount <= 0) break; } Log.Info("DVRMS2WMV: pre-run done"); Log.Info("DVRMS2WMV: Get duration of movie"); mediaControl.Stop(); FilterState state; mediaControl.GetState(500, out state); GC.Collect(); GC.Collect(); GC.Collect(); GC.WaitForPendingFinalizers(); Log.Info("DVRMS2WMV: reconnect mpeg2 video codec->ASF WM Writer"); graphBuilder.RemoveFilter(fileWriterbase); if (!AddWmAsfWriter(outputFilename, quality, standard)) return false; Log.Info("DVRMS2WMV: Start transcoding"); hr = mediaControl.Run(); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:unable to start graph :0x{0:X}", hr); Cleanup(); return false; } } catch (Exception e) { // TODO: Handle exceptions. Log.Error("unable to transcode file:{0} message:{1}", info.file, e.Message); return false; } return true; }