video: add initial implementation for video_bink

This commit is contained in:
nillerusr 2022-10-13 17:55:10 +03:00
parent 2f15ebbfb8
commit cf44c39aaf
8 changed files with 3326 additions and 0 deletions

View File

@ -0,0 +1,51 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// File: quicktime_common.h
//
// QuickTime limits and constants shared among all QuickTime functions
//
//=============================================================================
#ifndef QUICKTIME_COMMON_H
#define QUICKTIME_COMMON_H
#ifdef _WIN32
#pragma once
#endif
// constant that define the bounds of various inputs
static const int cMinVideoFrameWidth = 16;
static const int cMinVideoFrameHeight = 16;
static const int cMaxVideoFrameWidth = 2 * 2048;
static const int cMaxVideoFrameHeight = 2 * 2048;
static const int cMinFPS = 1;
static const int cMaxFPS = 600;
static const float cMinDuration = 0.016666666f; // 1/60th second
static const float cMaxDuration = 3600.0f; // 1 Hour
static const int cMinSampleRate = 11025; // 1/4 CD sample rate
static const int cMaxSampleRate = 88200; // 2x CD rate
#define NO_MORE_INTERESTING_TIMES -2
#define END_OF_QUICKTIME_MOVIE -1
extern char *COPY_STRING( const char *pString );
//-----------------------------------------------------------------------------
// Computes a power of two at least as big as the passed-in number
//-----------------------------------------------------------------------------
static inline int ComputeGreaterPowerOfTwo( int n )
{
int i = 1;
while ( i < n )
{
i <<= 1;
}
return i;
}
#endif // QUICKTIME_COMMON_H

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,220 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef BINK_MATERIAL_H
#define BINK_MATERIAL_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IFileSystem;
class IMaterialSystem;
class CBinkMaterial;
//-----------------------------------------------------------------------------
// Global interfaces - you already did the needed includes, right?
//-----------------------------------------------------------------------------
extern IFileSystem *g_pFileSystem;
extern IMaterialSystem *materials;
#include "video/ivideoservices.h"
#include "video_macros.h"
#include "bink_common.h"
#include "materialsystem/itexture.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/MaterialSystemUtil.h"
extern "C"
{
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
}
// -----------------------------------------------------------------------------
// Texture regenerator - callback to get new movie pixels into the texture
// -----------------------------------------------------------------------------
class CBinkMaterialRGBTextureRegenerator : public ITextureRegenerator
{
public:
CBinkMaterialRGBTextureRegenerator();
~CBinkMaterialRGBTextureRegenerator();
void SetSourceImage( uint8_t *SrcImage, int nWidth, int nHeight );
// Inherited from ITextureRegenerator
virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pRect );
virtual void Release();
private:
uint8_t *m_SrcImage;
int m_nSourceWidth;
int m_nSourceHeight;
};
// -----------------------------------------------------------------------------
// Class used to play a QuickTime video onto a texture
// -----------------------------------------------------------------------------
class CBinkMaterial : public IVideoMaterial
{
public:
CBinkMaterial();
~CBinkMaterial();
static const int MAX_FILENAME_LEN = 255;
static const int MAX_MATERIAL_NAME_LEN = 255;
static const int TEXTURE_SIZE_ALIGNMENT = 8;
// Initializes, shuts down the material
bool Init( const char *pMaterialName, const char *pFileName, VideoPlaybackFlags_t flags );
void Shutdown();
// Video information functions
virtual const char *GetVideoFileName(); // Gets the file name of the video this material is playing
virtual VideoResult_t GetLastResult(); // Gets detailed info on the last operation
virtual VideoFrameRate_t &GetVideoFrameRate(); // Returns the frame rate of the associated video in FPS
// Audio Functions
virtual bool HasAudio(); // Query if the video has an audio track
virtual bool SetVolume( float fVolume ); // Adjust the playback volume
virtual float GetVolume(); // Query the current volume
virtual void SetMuted( bool bMuteState ); // Mute/UnMutes the audio playback
virtual bool IsMuted(); // Query muted status
virtual VideoResult_t SoundDeviceCommand( VideoSoundDeviceOperation_t operation, void *pDevice = nullptr, void *pData = nullptr ); // Assign Sound Device for this Video Material
// Video playback state functions
virtual bool IsVideoReadyToPlay(); // Queries if the video material was initialized successfully and is ready for playback, but not playing or finished
virtual bool IsVideoPlaying(); // Is the video currently playing (and needs update calls, etc)
virtual bool IsNewFrameReady(); // Do we have a new frame to get & display?
virtual bool IsFinishedPlaying(); // Have we reached the end of the movie
virtual bool StartVideo(); // Starts the video playing
virtual bool StopVideo(); // Terminates the video playing
virtual void SetLooping( bool bLoopVideo ); // Sets the video to loop (or not)
virtual bool IsLooping(); // Queries if the video is looping
virtual void SetPaused( bool bPauseState ); // Pauses or Unpauses video playback
virtual bool IsPaused(); // Queries if the video is paused
// Position in playback functions
virtual float GetVideoDuration(); // Returns the duration of the associated video in seconds
virtual int GetFrameCount(); // Returns the total number of (unique) frames in the video
virtual bool SetFrame( int FrameNum ); // Sets the current frame # in the video to play next
virtual int GetCurrentFrame(); // Gets the current frame # for the video playback, 0 Based
virtual bool SetTime( float flTime ); // Sets the video playback to specified time (in seconds)
virtual float GetCurrentVideoTime(); // Gets the current time in the video playback
// Update function
virtual bool Update(); // Updates the video frame to reflect the time passed, true = new frame available
// Material / Texture Info functions
virtual IMaterial *GetMaterial(); // Gets the IMaterial associated with an video material
virtual void GetVideoTexCoordRange( float *pMaxU, float *pMaxV ) ; // Returns the max texture coordinate of the video portion of the material surface ( 0.0, 0.0 to U, V )
virtual void GetVideoImageSize( int *pWidth, int *pHeight ); // Returns the frame size of the Video Image Frame in pixels ( the stored in a subrect of the material itself)
private:
friend class CBinkMaterialRGBTextureRegenerator;
void Reset(); // clears internal state
void SetFileName( const char *theMovieFileName );
VideoResult_t SetResult( VideoResult_t status );
// Initializes, shuts down the video stream
void OpenMovie( const char *theMovieFileName );
void CloseFile();
// Initializes, shuts down the procedural texture
void CreateProceduralTexture( const char *pTextureName );
void DestroyProceduralTexture();
// Initializes, shuts down the procedural material
void CreateProceduralMaterial( const char *pMaterialName );
void DestroyProceduralMaterial();
CBinkMaterialRGBTextureRegenerator m_TextureRegen;
VideoResult_t m_LastResult;
CMaterialReference m_Material; // Ref to Material used for rendering the video frame
CTextureReference m_Texture; // Ref to the renderable texture which contains the most recent video frame (in a sub-rect)
float m_TexCordU; // Max U texture coordinate of the texture sub-rect which holds the video frame
float m_TexCordV; // Max V texture coordinate of the texture sub-rect which holds the video frame
int m_VideoFrameWidth; // Size of the movie frame in pixels
int m_VideoFrameHeight;
char *m_pFileName; // resolved filename of the movie being played
VideoPlaybackFlags_t m_PlaybackFlags; // option flags user supplied
bool m_bInitCalled;
bool m_bMovieInitialized;
bool m_bMoviePlaying;
bool m_bMovieFinishedPlaying;
bool m_bMoviePaused;
bool m_bLoopMovie;
bool m_bHasAudio;
bool m_bMuted;
float m_CurrentVolume;
// QuickTime Stuff
float m_QTMovieTimeScale;
float m_QTMoviefloat; // Units per second
float m_QTMovieDuration; // movie duration in float Units Per Second
float m_QTMovieDurationinSec; // movie duration in seconds
VideoFrameRate_t m_QTMovieFrameRate; // Frame Rate of movie
int m_QTMovieFrameCount;
double m_MovieFirstFrameTime;
double m_NextInterestingTimeToPlay;
float m_MoviePauseTime;
// AV stuff
AVFrame *m_AVFrame;
AVPacket *m_AVPkt;
AVFormatContext *m_AVFmtCtx;
int m_AVVideoStreamID;
int m_AVAudioStreamID;
AVCodecContext *m_AVVideoDecCtx ;
AVCodecContext *m_AVAudioDecCtx ;
AVStream *m_AVVideoStream;
AVStream *m_AVAudioStream;
int m_AVPixFormat;
double m_MovieFrameDuration;
uint8_t *m_AVVideoData[4];
uint8_t *m_RGBData;
int m_AVVideoLinesize[4];
};
#endif // BINK_MATERIAL_H

View File

@ -0,0 +1,345 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#include "bink_video.h"
#include "video_macros.h"
#include "filesystem.h"
#include "tier0/icommandline.h"
#include "tier1/strtools.h"
#include "tier1/utllinkedlist.h"
#include "tier1/KeyValues.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/MaterialSystemUtil.h"
#include "materialsystem/itexture.h"
#include "vtf/vtf.h"
#include "pixelwriter.h"
#include "tier2/tier2.h"
#include "platform.h"
#include "tier0/memdbgon.h"
#include "bink_material.h"
// ===========================================================================
// Singleton to expose Bink video subsystem
// ===========================================================================
static CBinkVideoSubSystem g_BinkSystem;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CBinkVideoSubSystem, IVideoSubSystem, VIDEO_SUBSYSTEM_INTERFACE_VERSION, g_BinkSystem );
// ===========================================================================
// List of file extensions and features supported by this subsystem
// ===========================================================================
VideoFileExtensionInfo_t s_BinkExtensions[] =
{
{ ".bik", VideoSystem::BINK, VideoSystemFeature::PLAY_VIDEO_FILE_IN_MATERIAL },
};
const int s_BinkExtensionCount = ARRAYSIZE( s_BinkExtensions );
const VideoSystemFeature_t CBinkVideoSubSystem::DEFAULT_FEATURE_SET = VideoSystemFeature::PLAY_VIDEO_FILE_IN_MATERIAL;
// ===========================================================================
// CBinkVideoSubSystem class
// ===========================================================================
CBinkVideoSubSystem::CBinkVideoSubSystem() :
m_bBinkInitialized( false ),
m_LastResult( VideoResult::SUCCESS ),
m_CurrentStatus( VideoSystemStatus::NOT_INITIALIZED ),
m_AvailableFeatures( CBinkVideoSubSystem::DEFAULT_FEATURE_SET ),
m_pCommonServices( nullptr )
{
}
CBinkVideoSubSystem::~CBinkVideoSubSystem()
{
ShutdownBink(); // Super redundant safety check
}
// ===========================================================================
// IAppSystem methods
// ===========================================================================
bool CBinkVideoSubSystem::Connect( CreateInterfaceFn factory )
{
if ( !BaseClass::Connect( factory ) )
{
return false;
}
if ( g_pFullFileSystem == nullptr || materials == nullptr )
{
Msg( "Bink video subsystem failed to connect to missing a required system\n" );
return false;
}
return true;
}
void CBinkVideoSubSystem::Disconnect()
{
BaseClass::Disconnect();
}
void* CBinkVideoSubSystem::QueryInterface( const char *pInterfaceName )
{
if ( IS_NOT_EMPTY( pInterfaceName ) )
{
if ( V_strncmp( pInterfaceName, VIDEO_SUBSYSTEM_INTERFACE_VERSION, Q_strlen( VIDEO_SUBSYSTEM_INTERFACE_VERSION ) + 1) == STRINGS_MATCH )
{
return (IVideoSubSystem*) this;
}
}
return nullptr;
}
InitReturnVal_t CBinkVideoSubSystem::Init()
{
InitReturnVal_t nRetVal = BaseClass::Init();
if ( nRetVal != INIT_OK )
{
return nRetVal;
}
return INIT_OK;
}
void CBinkVideoSubSystem::Shutdown()
{
// Make sure we shut down Bink
ShutdownBink();
BaseClass::Shutdown();
}
// ===========================================================================
// IVideoSubSystem identification methods
// ===========================================================================
VideoSystem_t CBinkVideoSubSystem::GetSystemID()
{
return VideoSystem::BINK;
}
VideoSystemStatus_t CBinkVideoSubSystem::GetSystemStatus()
{
return m_CurrentStatus;
}
VideoSystemFeature_t CBinkVideoSubSystem::GetSupportedFeatures()
{
return m_AvailableFeatures;
}
const char* CBinkVideoSubSystem::GetVideoSystemName()
{
return "BINK";
}
// ===========================================================================
// IVideoSubSystem setup and shutdown services
// ===========================================================================
bool CBinkVideoSubSystem::InitializeVideoSystem( IVideoCommonServices *pCommonServices )
{
m_AvailableFeatures = DEFAULT_FEATURE_SET; // Put here because of issue with static const int, binary OR and DEBUG builds
AssertPtr( pCommonServices );
m_pCommonServices = pCommonServices;
return ( m_bBinkInitialized ) ? true : SetupBink();
}
bool CBinkVideoSubSystem::ShutdownVideoSystem()
{
return ( m_bBinkInitialized ) ? ShutdownBink() : true;
}
VideoResult_t CBinkVideoSubSystem::VideoSoundDeviceCMD( VideoSoundDeviceOperation_t operation, void *pDevice, void *pData )
{
switch ( operation )
{
case VideoSoundDeviceOperation::SET_DIRECT_SOUND_DEVICE:
{
return SetResult( VideoResult::OPERATION_NOT_SUPPORTED );
}
case VideoSoundDeviceOperation::SET_MILES_SOUND_DEVICE:
case VideoSoundDeviceOperation::HOOK_X_AUDIO:
{
return SetResult( VideoResult::OPERATION_NOT_SUPPORTED );
}
default:
{
return SetResult( VideoResult::UNKNOWN_OPERATION );
}
}
}
// ===========================================================================
// IVideoSubSystem supported extensions & features
// ===========================================================================
int CBinkVideoSubSystem::GetSupportedFileExtensionCount()
{
return s_BinkExtensionCount;
}
const char* CBinkVideoSubSystem::GetSupportedFileExtension( int num )
{
return ( num < 0 || num >= s_BinkExtensionCount ) ? nullptr : s_BinkExtensions[num].m_FileExtension;
}
VideoSystemFeature_t CBinkVideoSubSystem::GetSupportedFileExtensionFeatures( int num )
{
return ( num < 0 || num >= s_BinkExtensionCount ) ? VideoSystemFeature::NO_FEATURES : s_BinkExtensions[num].m_VideoFeatures;
}
// ===========================================================================
// IVideoSubSystem Video Playback and Recording Services
// ===========================================================================
VideoResult_t CBinkVideoSubSystem::PlayVideoFileFullScreen( const char *filename, void *mainWindow, int windowWidth, int windowHeight, int desktopWidth, int desktopHeight, bool windowed, float forcedMinTime, VideoPlaybackFlags_t playbackFlags )
{
return SetResult( VideoResult::FEATURE_NOT_AVAILABLE );
}
// ===========================================================================
// IVideoSubSystem Video Material Services
// note that the filename is absolute and has already resolved any paths
// ===========================================================================
IVideoMaterial* CBinkVideoSubSystem::CreateVideoMaterial( const char *pMaterialName, const char *pVideoFileName, VideoPlaybackFlags_t flags )
{
SetResult( VideoResult::BAD_INPUT_PARAMETERS );
AssertExitN( m_CurrentStatus == VideoSystemStatus::OK && IS_NOT_EMPTY( pMaterialName ) || IS_NOT_EMPTY( pVideoFileName ) );
CBinkMaterial *pVideoMaterial = new CBinkMaterial();
if ( pVideoMaterial == nullptr || pVideoMaterial->Init( pMaterialName, pVideoFileName, flags ) == false )
{
SAFE_DELETE( pVideoMaterial );
SetResult( VideoResult::VIDEO_ERROR_OCCURED );
return nullptr;
}
IVideoMaterial *pInterface = (IVideoMaterial*) pVideoMaterial;
m_MaterialList.AddToTail( pInterface );
SetResult( VideoResult::SUCCESS );
return pInterface;
}
VideoResult_t CBinkVideoSubSystem::DestroyVideoMaterial( IVideoMaterial *pVideoMaterial )
{
AssertExitV( m_CurrentStatus == VideoSystemStatus::OK, SetResult( VideoResult::SYSTEM_NOT_AVAILABLE ) );
AssertPtrExitV( pVideoMaterial, SetResult( VideoResult::BAD_INPUT_PARAMETERS ) );
if ( m_MaterialList.Find( pVideoMaterial ) != -1 )
{
CBinkMaterial *pObject = (CBinkMaterial*) pVideoMaterial;
pObject->Shutdown();
delete pObject;
m_MaterialList.FindAndFastRemove( pVideoMaterial );
return SetResult( VideoResult::SUCCESS );
}
return SetResult (VideoResult::MATERIAL_NOT_FOUND );
}
// ===========================================================================
// IVideoSubSystem Video Recorder Services
// ===========================================================================
IVideoRecorder* CBinkVideoSubSystem::CreateVideoRecorder()
{
SetResult( VideoResult::FEATURE_NOT_AVAILABLE );
return nullptr;
}
VideoResult_t CBinkVideoSubSystem::DestroyVideoRecorder( IVideoRecorder *pRecorder )
{
return SetResult( VideoResult::FEATURE_NOT_AVAILABLE );
}
VideoResult_t CBinkVideoSubSystem::CheckCodecAvailability( VideoEncodeCodec_t codec )
{
AssertExitV( m_CurrentStatus == VideoSystemStatus::OK, SetResult( VideoResult::SYSTEM_NOT_AVAILABLE ) );
AssertExitV( codec >= VideoEncodeCodec::DEFAULT_CODEC && codec < VideoEncodeCodec::CODEC_COUNT, SetResult( VideoResult::BAD_INPUT_PARAMETERS ) );
return SetResult( VideoResult::FEATURE_NOT_AVAILABLE );
}
// ===========================================================================
// Status support
// ===========================================================================
VideoResult_t CBinkVideoSubSystem::GetLastResult()
{
return m_LastResult;
}
VideoResult_t CBinkVideoSubSystem::SetResult( VideoResult_t status )
{
m_LastResult = status;
return status;
}
// ===========================================================================
// Bink Initialization & Shutdown
// ===========================================================================
bool CBinkVideoSubSystem::SetupBink()
{
SetResult( VideoResult::INITIALIZATION_ERROR_OCCURED);
AssertExitF( m_bBinkInitialized == false );
// This is set early to indicate we have already been through here, even if we error out for some reason
m_bBinkInitialized = true;
m_CurrentStatus = VideoSystemStatus::OK;
m_AvailableFeatures = DEFAULT_FEATURE_SET;
// $$INIT CODE HERE$$
// Note that we are now open for business....
m_bBinkInitialized = true;
SetResult( VideoResult::SUCCESS );
return true;
}
bool CBinkVideoSubSystem::ShutdownBink()
{
if ( m_bBinkInitialized && m_CurrentStatus == VideoSystemStatus::OK )
{
}
m_bBinkInitialized = false;
m_CurrentStatus = VideoSystemStatus::NOT_INITIALIZED;
m_AvailableFeatures = VideoSystemFeature::NO_FEATURES;
SetResult( VideoResult::SUCCESS );
return true;
}

View File

@ -0,0 +1,109 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================
#ifndef BINK_VIDEO_H
#define BINK_VIDEO_H
#ifdef _WIN32
#pragma once
#endif
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IFileSystem;
class IMaterialSystem;
class CQuickTimeMaterial;
//-----------------------------------------------------------------------------
// Global interfaces - you already did the needed includes, right?
//-----------------------------------------------------------------------------
extern IFileSystem *g_pFileSystem;
extern IMaterialSystem *materials;
#include "video/ivideoservices.h"
#include "videosubsystem.h"
#include "utlvector.h"
#include "tier1/KeyValues.h"
#include "tier0/platform.h"
// -----------------------------------------------------------------------------
// CQuickTimeVideoSubSystem - Implementation of IVideoSubSystem
// -----------------------------------------------------------------------------
class CBinkVideoSubSystem : public CTier2AppSystem< IVideoSubSystem >
{
typedef CTier2AppSystem< IVideoSubSystem > BaseClass;
public:
CBinkVideoSubSystem();
~CBinkVideoSubSystem();
// Inherited from IAppSystem
virtual bool Connect( CreateInterfaceFn factory );
virtual void Disconnect();
virtual void *QueryInterface( const char *pInterfaceName );
virtual InitReturnVal_t Init();
virtual void Shutdown();
// Inherited from IVideoSubSystem
// SubSystem Identification functions
virtual VideoSystem_t GetSystemID();
virtual VideoSystemStatus_t GetSystemStatus();
virtual VideoSystemFeature_t GetSupportedFeatures();
virtual const char *GetVideoSystemName();
// Setup & Shutdown Services
virtual bool InitializeVideoSystem( IVideoCommonServices *pCommonServices );
virtual bool ShutdownVideoSystem();
virtual VideoResult_t VideoSoundDeviceCMD( VideoSoundDeviceOperation_t operation, void *pDevice = nullptr, void *pData = nullptr );
// get list of file extensions and features we support
virtual int GetSupportedFileExtensionCount();
virtual const char *GetSupportedFileExtension( int num );
virtual VideoSystemFeature_t GetSupportedFileExtensionFeatures( int num );
// Video Playback and Recording Services
virtual VideoResult_t PlayVideoFileFullScreen( const char *filename, void *mainWindow, int windowWidth, int windowHeight, int desktopWidth, int desktopHeight, bool windowed, float forcedMinTime, VideoPlaybackFlags_t playbackFlags );
// Create/destroy a video material
virtual IVideoMaterial *CreateVideoMaterial( const char *pMaterialName, const char *pVideoFileName, VideoPlaybackFlags_t flags );
virtual VideoResult_t DestroyVideoMaterial( IVideoMaterial *pVideoMaterial );
// Create/destroy a video encoder
virtual IVideoRecorder *CreateVideoRecorder();
virtual VideoResult_t DestroyVideoRecorder( IVideoRecorder *pRecorder );
virtual VideoResult_t CheckCodecAvailability( VideoEncodeCodec_t codec );
virtual VideoResult_t GetLastResult();
private:
bool SetupBink();
bool ShutdownBink();
VideoResult_t SetResult( VideoResult_t status );
bool m_bBinkInitialized;
VideoResult_t m_LastResult;
VideoSystemStatus_t m_CurrentStatus;
VideoSystemFeature_t m_AvailableFeatures;
IVideoCommonServices *m_pCommonServices;
CUtlVector< IVideoMaterial* > m_MaterialList;
CUtlVector< IVideoRecorder* > m_RecorderList;
static const VideoSystemFeature_t DEFAULT_FEATURE_SET;
};
#endif // BINK_VIDEO_H

55
video/video_bink/wscript Executable file
View File

@ -0,0 +1,55 @@
#! /usr/bin/env python
# encoding: utf-8
from waflib import Utils
import os
top = '.'
PROJECT_NAME = 'video_bink'
def options(opt):
# stub
return
def configure(conf):
return
def build(bld):
source = [
'bink_material.cpp',
'bink_video.cpp',
'yuv_rgb.c',
'../../public/tier0/memoverride.cpp'
]
includes = [
'.',
'../../public',
'../../public/tier0',
'../../public/tier1',
'../../common',
'../'
] + bld.env.INCLUDES_SDL2
defines = []
libs = ['tier0','tier1','tier2','tier3','vstdlib', 'AVCODEC', 'AVUTIL', 'AVFORMAT']
if bld.env.DEST_OS == 'win32':
libs += ['USER32']
install_path = bld.env.LIBDIR
bld.shlib(
source = source,
target = PROJECT_NAME,
name = PROJECT_NAME,
features = 'c cxx',
includes = includes,
defines = defines,
use = libs,
install_path = install_path,
subsystem = bld.env.MSVC_SUBSYSTEM,
idx = bld.get_taskgen_count()
)

1312
video/video_bink/yuv_rgb.c Normal file

File diff suppressed because it is too large Load Diff

155
video/video_bink/yuv_rgb.h Normal file
View File

@ -0,0 +1,155 @@
// Copyright 2016 Adrien Descamps
// Distributed under BSD 3-Clause License
// Provide optimized functions to convert images from 8bits yuv420 to rgb24 format
// There are a few slightly different variations of the YCbCr color space with different parameters that
// change the conversion matrix.
// The three most common YCbCr color space, defined by BT.601, BT.709 and JPEG standard are implemented here.
// See the respective standards for details
// The matrix values used are derived from http://www.equasys.de/colorconversion.html
// YUV420 is stored as three separate channels, with U and V (Cb and Cr) subsampled by a 2 factor
// For conversion from yuv to rgb, no interpolation is done, and the same UV value are used for 4 rgb pixels. This
// is suboptimal for image quality, but by far the fastest method.
// For all methods, width and height should be even, if not, the last row/column of the result image won't be affected.
// For sse methods, if the width if not divisable by 32, the last (width%32) pixels of each line won't be affected.
#include <stdint.h>
typedef enum
{
YCBCR_JPEG,
YCBCR_601,
YCBCR_709
} YCbCrType;
#ifdef __cplusplus
extern "C" {
#endif
// yuv to rgb, standard c implementation
void yuv420_rgb24_std(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv to rgb, yuv in nv12 semi planar format
void nv12_rgb24_std(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *uv, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv to rgb, yuv in nv12 semi planar format
void nv21_rgb24_std(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *uv, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv to rgb, sse implementation
// pointers must be 16 byte aligned, and strides must be divisable by 16
void yuv420_rgb24_sse(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv to rgb, sse implementation
// pointers do not need to be 16 byte aligned
void yuv420_rgb24_sseu(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *u, const uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv nv12 to rgb, sse implementation
// pointers must be 16 byte aligned, and strides must be divisable by 16
void nv12_rgb24_sse(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *uv, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv nv12 to rgb, sse implementation
// pointers do not need to be 16 byte aligned
void nv12_rgb24_sseu(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *uv, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv nv21 to rgb, sse implementation
// pointers must be 16 byte aligned, and strides must be divisable by 16
void nv21_rgb24_sse(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *uv, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// yuv nv21 to rgb, sse implementation
// pointers do not need to be 16 byte aligned
void nv21_rgb24_sseu(
uint32_t width, uint32_t height,
const uint8_t *y, const uint8_t *uv, uint32_t y_stride, uint32_t uv_stride,
uint8_t *rgb, uint32_t rgb_stride,
YCbCrType yuv_type);
// rgb to yuv, standard c implementation
void rgb24_yuv420_std(
uint32_t width, uint32_t height,
const uint8_t *rgb, uint32_t rgb_stride,
uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
YCbCrType yuv_type);
// rgb to yuv, sse implementation
// pointers must be 16 byte aligned, and strides must be divisible by 16
void rgb24_yuv420_sse(
uint32_t width, uint32_t height,
const uint8_t *rgb, uint32_t rgb_stride,
uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
YCbCrType yuv_type);
// rgb to yuv, sse implementation
// pointers do not need to be 16 byte aligned
void rgb24_yuv420_sseu(
uint32_t width, uint32_t height,
const uint8_t *rgb, uint32_t rgb_stride,
uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
YCbCrType yuv_type);
// rgba to yuv, standard c implementation
// alpha channel is ignored
void rgb32_yuv420_std(
uint32_t width, uint32_t height,
const uint8_t *rgba, uint32_t rgba_stride,
uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
YCbCrType yuv_type);
// rgba to yuv, sse implementation
// pointers must be 16 byte aligned, and strides must be divisible by 16
// alpha channel is ignored
void rgb32_yuv420_sse(
uint32_t width, uint32_t height,
const uint8_t *rgba, uint32_t rgba_stride,
uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
YCbCrType yuv_type);
// rgba to yuv, sse implementation
// pointers do not need to be 16 byte aligned
// alpha channel is ignored
void rgb32_yuv420_sseu(
uint32_t width, uint32_t height,
const uint8_t *rgba, uint32_t rgba_stride,
uint8_t *y, uint8_t *u, uint8_t *v, uint32_t y_stride, uint32_t uv_stride,
YCbCrType yuv_type);
#ifdef __cplusplus
}
#endif