View Single Post
Old 18th August 2014, 14:00   #8  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
ok, thanks for looking at it
Code:
// HistByLine plugin
//
// Written by jmac698
// Copyleft 8-14-2014
// 
// You may use this plugin however you wish,
// and distribute it under the terms of the GNU GPL.
//
// HISTORY:
// - Alpha 0.3: mode 0 is implemented and works, returns YV12 output only
// - tested with inputs of YV12, YUY2, Y8
//
// Plugin parameters:
// ------------------
// HistByLine(clip, int mode)
//
// clip    clip: input clip, can be YUY2, YV12 or Y8
// int     mode (default: 0): 
// 0 - if count>0 then luma=255
// 1 - scaled count with 255=1.0
// 2 - lsb of count
// 3 - msb of count
// 
// output: RGB32 color image
//
// Based on DemosaicCPP by StainlessS

#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include "Avisynth.h"


// class HistByLineCPP
class HistByLineCPP : public GenericVideoFilter {   
private:
	// ---------- avisynth.h interface extension - begin ----------
	// The following is missing from avisynth.h  version 3 and is needed by this v2.5 plugin.
	//
	//                    From Avisynth.h Version 5
	// CS_Shift_Sample_Bits = 16,
	// CS_Sample_Bits_Mask  = 7 << CS_Shift_Sample_Bits,
	// CS_Sample_Bits_8     = 0 << CS_Shift_Sample_Bits,
	//
	// Planar match mask  1111.0000.0000.0111.0000.0111.0000.0111	// 0xF0070707
	// Planar signature   10xx.0000.0000.00xx.0000.00xx.00xx.00xx	// 0xCFFCFCCC, 0x80000000
	// Planar filter mask 1111.1111.1111.1111.1111.1111.1100.1111	// 0xFFFFFFCF
	//
	enum {
		V25_CS_Shift_Sample_Bits    = 16,
		V25_CS_Sample_Bits_Mask     = (7 << V25_CS_Shift_Sample_Bits),
		V25_CS_Sample_Bits_8        = (0 << V25_CS_Shift_Sample_Bits),
		V25_CS_PLANAR_MASK          = 0xF0070707,
		V25_CS_PLANAR_FILTER        = 0xFFFFFFCF,
		V25_CS_Y                    = VideoInfo::CS_PLANAR | VideoInfo::CS_INTERLEAVED | VideoInfo::CS_YUV,
		V25_CS_Y8                   = V25_CS_Y | V25_CS_Sample_Bits_8
	};			

	bool V25_IsY8(VideoInfo&vix) const { return (vix.pixel_type & V25_CS_PLANAR_MASK) == (V25_CS_Y8 & V25_CS_PLANAR_FILTER);}
	// ---------- avisynth_c interface extension - end ----------

	const int mode;

	VideoInfo src_vi;
public:
	HistByLineCPP(PClip _child,int _mode,IScriptEnvironment* env);	// Constructor
	~HistByLineCPP();															// Destructor
	PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);			// GetFrame
};



// This is the constructor.
HistByLineCPP::HistByLineCPP(PClip _child,int _mode,IScriptEnvironment* env) :
		GenericVideoFilter(_child),mode(_mode) {

	if(!vi.IsYV12() && !vi.IsYUY2() && !V25_IsY8(vi))			// Synthesized for Y8
		env->ThrowError("Input video format can be: YUY2, YV12, Y8");
	src_vi = vi;			// remember original source vi.
	// we copied the clip type of the source, now we make some modifications
	// Set up VideoInfo to return new colorspace YV12
	vi.pixel_type = VideoInfo::CS_YV12; // RGB would be CS_BGR32
	vi.width = 256; // only need width of 256 to hold histogram samples
}


// This is the destructor definition. This is called when the filter is destroyed.
HistByLineCPP::~HistByLineCPP()
{}										// Empty Destructor


// GetFrame() Called by Avisynth to get frame n
PVideoFrame __stdcall HistByLineCPP::GetFrame(int n, IScriptEnvironment* env) {
	// destination
	PVideoFrame dest_frame;
	BYTE* dest_data;
	unsigned int dest_pitch;
	unsigned int dest_height;
	unsigned int dest_row_size;
	unsigned int dest_uv_pitch; // for planar (yv12)
	unsigned int dest_uv_height;
	BYTE* dest_data_u;
	BYTE* dest_data_v;
	unsigned int dest_uv_row_size;
	
	dest_frame	=	env->NewVideoFrame(vi);
	dest_data = dest_frame->GetWritePtr(PLANAR_Y);
	dest_pitch = dest_frame->GetPitch(PLANAR_Y);
	dest_height = dest_frame->GetHeight(PLANAR_Y);
	dest_row_size = dest_frame->GetRowSize(PLANAR_Y);
	dest_uv_pitch = dest_frame->GetPitch(PLANAR_U);
	dest_uv_height = dest_frame->GetHeight(PLANAR_U);
	dest_data_u = dest_frame->GetWritePtr(PLANAR_U);
	dest_data_v = dest_frame->GetWritePtr(PLANAR_V);
	dest_uv_row_size = dest_frame->GetRowSize(PLANAR_U);

	// source
	PVideoFrame src_frame;
	CONST BYTE* src_data;
	unsigned int src_pitch;
	unsigned int src_row_size;									// in bytes!
	unsigned int src_height;
	unsigned int src_inc;										// next pixel in row
	
	src_frame	=	child->GetFrame(n, env);

	if(src_vi.IsYV12()) {
		src_data	=	src_frame->GetReadPtr(PLANAR_Y);
		src_pitch	=	src_frame->GetPitch(PLANAR_Y);
		src_row_size=	src_frame->GetRowSize(PLANAR_Y);		// in bytes!
		src_height	=	src_frame->GetHeight(PLANAR_Y);
		src_inc		=	1;
	} else if(src_vi.IsYUY2()) {
		src_data	=	src_frame->GetReadPtr();
		src_pitch	=	src_frame->GetPitch();
		src_row_size=	src_frame->GetRowSize();				// in bytes!
		src_height	=	src_frame->GetHeight();
		src_inc		=	2;
	} else if(V25_IsY8(src_vi)) {
		src_data	=	src_frame->GetReadPtr();
		src_pitch	=	src_frame->GetPitch();
		src_row_size=	src_frame->GetRowSize();				// in bytes!
		src_height	=	src_frame->GetHeight();
		src_inc		=	1;
	} else {				// somethings very wrong
		return dest_frame;										// dest_frame is junk ???
	}

	
	unsigned int x, y;

	// RGB is upside down
	// dest_data += (dest_height - 1) * dest_pitch; // only needed if returning RGB

	// make dest_frame luma 0
	for (y = 0; y < dest_height; ++y) {
		for (x = 0; x < dest_row_size; ++x) {
			dest_data[x] = 0; // initialize luma of dest frame to 0
		}
		dest_data += dest_pitch;
	}
	
	// make dest_frame grey (for planar formats)
	for (y = 0; y < dest_uv_height; ++y) {
		for (x = 0; x < dest_uv_row_size; ++x) {
			dest_data_u[x] = 128;
			dest_data_v[x] = 128;
		}
		dest_data_u += dest_uv_pitch;
		dest_data_v += dest_uv_pitch;
	}

	dest_data = dest_frame->GetWritePtr(PLANAR_Y); // reset dest_data


	for (y = 0; y < src_height; ++y) {
		for (x = 0; x < src_row_size; x += src_inc) {
			// int mode (default: 0): 
			// 0 - if count>0 then luma=255
			// 1 - scaled count with 255=1.0
			// 2 - lsb of count
			// 3 - msb of count
			if (mode == 0) {
					dest_data[src_data[x]] = 255; //assumes dest_data was initialized with 0's
			}
			
		}
		src_data += src_pitch;
		// dest_data -= dest_pitch; // decrement in the case of RGB
		dest_data += dest_pitch;
	}

	return dest_frame;
}




AVSValue __cdecl Create_HistByLineCPP(AVSValue args, void* user_data, IScriptEnvironment* env) {
	
	return new HistByLineCPP(						// Arguments to the Filter class Constructor of HistByLineCPP class.
			args[0].AsClip(),					// Clip
			args[1].AsInt(0),					// mode
			env								
			);
}	


extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(IScriptEnvironment* env) {

    env->AddFunction(
		"HistByLineCPP",				// The name of the filter in Avisynth.
		"c[mode]i",
		Create_HistByLineCPP,			// The function Avisynth will call to create an instance of the filter.
		0
		);

	// Arguments is a string that defines the types and optional names of the arguments for you filter.
    // c - Video Clip
    // i - Integer number
    // f - Float number
    // s - String
    // b - boolean
	// . - Any type (dot)
	//      Array Specifiers
	// i* - Integer Array, zero or more
	// i+ - Integer Array, one or more
	// .* - Any type Array, zero or more
	// .+ - Any type Array, one or more
	//      Etc

	return "`HistByLineCPP' HistByLineCPP plugin";	// A freeform name of the plugin.
}

Last edited by jmac698; 18th August 2014 at 15:28. Reason: Updated code to Alpha 0.2; working
jmac698 is offline   Reply With Quote