Snippets

Primo Software AVBlocks: C#: Overlay JPEG Images Over YUV

Created by Svilen Stoilov last modified
using System;
using System.IO;
using System.Reflection;
using PrimoSoftware.AVBlocks;

namespace overlay_yuv_jpegs_sample
{
    class Program
    {
        static int Main(string[] args)
        {
            Library.Initialize();

            // Set license information. To run AVBlocks in demo mode, comment the next line out
            // Library.SetLicense("<license-string>");

            string inputFile = Path.Combine(ExeDir, @"..\sample-resources\mov\big_buck_bunny_trailer_iphone.m4v");
            string outputFile = "overlay_yuv_jpegs.mp4";
            const int imageOverlayFrames = 250;
            string imageOverlayFiles = Path.Combine(ExeDir, @"..\sample-resources\overlay\cube\cube{0:d4} (128x96).jpg");

            var info = new MediaInfo()
            {
                InputFile = inputFile
            };

            if (!info.Load())
            {
                PrintError("load info", info.Error);
                return 1;
            }

            VideoStreamInfo uncompressedVideo = null;
            foreach (var stream in info.Streams)
            {
                if (stream.MediaType == MediaType.Video)
                {
                    uncompressedVideo = stream.Clone() as VideoStreamInfo;
                    break;
                }
            }
            uncompressedVideo.StreamType = StreamType.UncompressedVideo;
            uncompressedVideo.ColorFormat = ColorFormat.YUV420;

            var decoder = CreateDecoder(inputFile);
            if (!decoder.Open())
            {
                PrintError("decoder open", decoder.Error);
                return 1;
            }

            var overlay = new Transcoder();

            try { System.IO.File.Delete(outputFile); }
            catch { }

            var outputVideo = (VideoStreamInfo)uncompressedVideo.Clone();
            outputVideo.StreamType = StreamType.H264;

            var encoder = CreateEncoder(uncompressedVideo, outputVideo, outputFile);
            if (!encoder.Open())
            {
                PrintError("encoder open", encoder.Error);
                return 1;
            }

            int outputIndex;
            var decodedSample = new MediaSample();
            var overlayedSample = new MediaSample();
            int decodedSamples = 0;
            int overlayedSamples = 0;
            int encodedSamples = 0;

            while (true)
            {
                if (!decoder.Pull(out outputIndex, decodedSample))
                {
                    PrintError("decoder pull", decoder.Error);
                    break;
                }
                ++decodedSamples;

                var imageOverlayFile = string.Format(imageOverlayFiles, overlayedSamples % imageOverlayFrames);

                if (!InitOverlay(overlay, imageOverlayFile, StreamType.Jpeg, uncompressedVideo))
                {
                    PrintError("overlay init", overlay.Error);
                    break;
                }

                if (!overlay.Push(0, decodedSample))
                {
                    PrintError("overlay push", overlay.Error);
                    break;
                }

                if (!overlay.Pull(out outputIndex, overlayedSample))
                {
                    PrintError("overlay pull", overlay.Error);
                    break;
                }
                ++overlayedSamples;


                if (!encoder.Push(0, overlayedSample))
                {
                    PrintError("encoder push", encoder.Error);
                    break;
                }
                ++encodedSamples;
            };

            decoder.Close();
            overlay.Close();
            encoder.Flush();
            encoder.Close();

            Console.WriteLine("samples decoded/overlayed/encoded: {0}/{1}/{2}",
                               decodedSamples, overlayedSamples, encodedSamples);

            Library.Shutdown();

            return (decodedSamples > 0 && decodedSamples == encodedSamples) ? 0 : 1;
        }
        static Transcoder CreateDecoder(string inputFile, VideoStreamInfo uncompressedInputVideo = null)
        {
            Transcoder transcoder = new Transcoder()
            {
                AllowDemoMode = true
            };

            var inSocket = new MediaSocket()
            {
                File = inputFile,
            };

            if (uncompressedInputVideo != null)
            {
                inSocket.Pins.Add(new MediaPin()
                {
                    StreamInfo = uncompressedInputVideo
                });

                inSocket.StreamType = StreamType.UncompressedVideo;
            }

            transcoder.Inputs.Add(inSocket);

            var outSocket = new MediaSocket()
            {
                File = null, // Pull
                StreamType = StreamType.UncompressedVideo
            };

            outSocket.Pins.Add(new MediaPin()
            {
                StreamInfo = new VideoStreamInfo()
                {
                    StreamType = StreamType.UncompressedVideo
                }
            });

            transcoder.Outputs.Add(outSocket);

            return transcoder;
        }

        static Transcoder CreateEncoder(VideoStreamInfo inputVideo, VideoStreamInfo outputVideo, string outputFile)
        {
            Transcoder transcoder = new Transcoder()
            {
                AllowDemoMode = true
            };


            var inSocket = new MediaSocket()
            {
                File = null, //Push
                StreamType = StreamType.UncompressedVideo,
            };

            inSocket.Pins.Add(new MediaPin()
            {
                StreamInfo = inputVideo
            });
            transcoder.Inputs.Add(inSocket);

            var outSocket = new MediaSocket()
            {
                File = outputFile,
            };

            outSocket.Pins.Add(new MediaPin()
            {
                StreamInfo = outputVideo
            });

            transcoder.Outputs.Add(outSocket);

            return transcoder;
        }

        static void SetOverlayParamsToPin(MediaPin pin, string imageOverlay, StreamType imageType)
        {
            var videoInfo = new VideoStreamInfo()
            {
                StreamType = imageType
            };

            pin.Params[Param.Video.Overlay.Mode] = AlphaCompositingMode.Atop;
            pin.Params[Param.Video.Overlay.BackgroundX] = 0;
            pin.Params[Param.Video.Overlay.BackgroundY] = 0;
            pin.Params[Param.Video.Overlay.BackgroundAlpha] = 1.0;
            pin.Params[Param.Video.Overlay.ForegroundBuffer] =
                           new MediaBuffer(System.IO.File.ReadAllBytes(imageOverlay));
            pin.Params[Param.Video.Overlay.ForegroundBufferFormat] = videoInfo;
            pin.Params[Param.Video.Overlay.ForegroundAlpha] = 1.0;
        }

        static bool InitOverlay(Transcoder t, string imageOverlay, StreamType imageType, VideoStreamInfo uncompressedVideo)
        {
            t.Close();
            t.Inputs.Clear();
            t.Outputs.Clear();

            var inSocket = new MediaSocket()
            {
                File = null, // Push
                StreamType = StreamType.UncompressedVideo,
            };

            inSocket.Pins.Add(new MediaPin()
            {
                StreamInfo = uncompressedVideo
            });
            t.Inputs.Add(inSocket);

            var outSocket = new MediaSocket()
            {
                File = null, // Pull
                StreamType = StreamType.UncompressedVideo
            };

            outSocket.Pins.Add(new MediaPin()
            {
                StreamInfo = uncompressedVideo
            });

            SetOverlayParamsToPin(outSocket.Pins[0], imageOverlay, imageType);

            t.Outputs.Add(outSocket);

            return t.Open();
        }

        static void PrintError(string action, ErrorInfo e)
        {
            if (action != null)
            {
                Console.Write("{0}: ", action);
            }

            if (ErrorFacility.Success == e.Facility)
            {
                Console.WriteLine("Success");
                return;
            }
            else
            {
                Console.WriteLine("{0}, facility:{1} code:{2} hint:{3}", e.Message , e.Facility, e.Code, e.Hint);
            }
        }

        static string exedir;
        static string ExeDir
        {
            get
            {
                if (exedir == null)
                    exedir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

                return exedir;
            }
        }
    }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.