/// <summary> /// <see cref="sws_getCachedContext(SwsContext*, int, int, AVPixelFormat, int, int, AVPixelFormat, int, SwsFilter*, SwsFilter*, double*)"/> /// <see cref="sws_scale(SwsContext*, byte*[], int[], int, int, byte*[], int[])"/> /// </summary> public static IEnumerable <Frame> ConvertFrames(this CodecContext c, IEnumerable <Frame> sourceFrames, ScaleFlag flags = ScaleFlag.Bilinear) { using var destFrame = c.CreateFrame(); int pts = 0; if (c.Codec.Type == MediaType.Video) { using var frameConverter = new FrameConverter(); foreach (var sourceFrame in sourceFrames) { frameConverter.ConvertFrame(sourceFrame, destFrame, flags); destFrame.Pts = pts++; yield return(destFrame); } } else if (c.Codec.Type == MediaType.Audio) { using var frameConverter = new SampleConverter(); foreach (var sourceFrame in sourceFrames) { frameConverter.ConvertFrame(destFrame, sourceFrame); destFrame.Pts = pts += c.FrameSize; yield return(destFrame); } } }
/// <summary> /// Convert to audio frame to <paramref name="dstFotmat"/> /// <para><see cref="DepthType"/> to <see cref="AVSampleFormat"/> mapping table. /// if <see cref="Mat.NumberOfChannels"/> > 1, use packet format, otherwise planar</para> /// <list type="table" > /// <item> /// <term><see cref="DepthType.Cv8U"/></term> /// <description1><see cref="AVSampleFormat.AV_SAMPLE_FMT_U8"/>/<see cref="AVSampleFormat.AV_SAMPLE_FMT_U8P"/></description1> /// </item> /// <item> /// <term><see cref="DepthType.Cv16S"/></term> /// <description1><see cref="AVSampleFormat.AV_SAMPLE_FMT_S16"/>/<see cref="AVSampleFormat.AV_SAMPLE_FMT_S16P"/></description1> /// </item> /// <item> /// <term><see cref="DepthType.Cv32S"/></term> /// <description1><see cref="AVSampleFormat.AV_SAMPLE_FMT_S32"/>/<see cref="AVSampleFormat.AV_SAMPLE_FMT_S32P"/></description1> /// </item> /// <item> /// <term><see cref="DepthType.Cv32F"/></term> /// <description1><see cref="AVSampleFormat.AV_SAMPLE_FMT_FLT"/>/<see cref="AVSampleFormat.AV_SAMPLE_FMT_FLTP"/></description1> /// </item> /// <item> /// <term><see cref="DepthType.Cv64F"/></term> /// <description1><see cref="AVSampleFormat.AV_SAMPLE_FMT_DBL"/>/<see cref="AVSampleFormat.AV_SAMPLE_FMT_DBLP"/></description1> /// </item> /// <item> /// <term><see cref="DepthType.Cv64F"/></term> /// <description1><see cref="AVSampleFormat.AV_SAMPLE_FMT_S64"/>/<see cref="AVSampleFormat.AV_SAMPLE_FMT_S64P"/></description1> /// </item> /// <item>NOTE: Emgucv not supported int64, mapping Cv64F to int64, /// so set Mat with int64 if <paramref name="dstFotmat"/> is <see cref="AVSampleFormat.AV_SAMPLE_FMT_S64"/> or <see cref="AVSampleFormat.AV_SAMPLE_FMT_S64P"/> /// </item> /// </list> /// </summary> /// <param name="mat"></param> /// <param name="dstFotmat">Default is auto format by <see cref="Mat.Depth"/> and <see cref="Mat.NumberOfChannels"/> use mapping table</param> /// <param name="dstSampleRate">Mat not have sample rate, set value here or later</param> /// <returns></returns> public static AudioFrame ToAudioFrame(this Mat mat, AVSampleFormat dstFotmat = AVSampleFormat.AV_SAMPLE_FMT_NONE, int dstSampleRate = 0) { AVSampleFormat srcformat; switch (mat.Depth) { case DepthType.Default: case DepthType.Cv8U: case DepthType.Cv8S: srcformat = mat.NumberOfChannels > 1 ? AVSampleFormat.AV_SAMPLE_FMT_U8 : AVSampleFormat.AV_SAMPLE_FMT_U8P; break; case DepthType.Cv16U: case DepthType.Cv16S: srcformat = mat.NumberOfChannels > 1 ? AVSampleFormat.AV_SAMPLE_FMT_S16 : AVSampleFormat.AV_SAMPLE_FMT_S16P; break; case DepthType.Cv32S: srcformat = mat.NumberOfChannels > 1 ? AVSampleFormat.AV_SAMPLE_FMT_S32 : AVSampleFormat.AV_SAMPLE_FMT_S32P; break; case DepthType.Cv32F: srcformat = mat.NumberOfChannels > 1 ? AVSampleFormat.AV_SAMPLE_FMT_FLT : AVSampleFormat.AV_SAMPLE_FMT_FLTP; break; case DepthType.Cv64F: srcformat = mat.NumberOfChannels > 1 ? AVSampleFormat.AV_SAMPLE_FMT_DBL : AVSampleFormat.AV_SAMPLE_FMT_DBLP; break; default: throw new FFmpegException(FFmpegException.NotSupportFormat); } if (dstFotmat != AVSampleFormat.AV_SAMPLE_FMT_NONE && dstFotmat != srcformat) { // converter must need set sample rate using (SampleConverter converter = new SampleConverter(dstFotmat, mat.NumberOfChannels > 1 ? mat.NumberOfChannels : mat.Height, mat.Width, Math.Min(1, dstSampleRate))) { AudioFrame frame = converter.ConvertFrame(MatToAudioFrame(mat, srcformat, Math.Min(1, dstSampleRate)), out int a, out int b); unsafe { // set real sample rate after convert ((AVFrame *)frame)->sample_rate = dstSampleRate; } } } return(MatToAudioFrame(mat, srcformat, dstSampleRate)); }