Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
14th August 2014, 20:19 | #1 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
plugin development: HistByLine
Hi,
Getting back into writing plugins again - and I've lost all the files I've ever had so, starting over. I modified and compiled DemosaicCPP. My test plugin simply copies a source to a destination clip, but the colour channels aren't being copied. Code:
vi.pixel_type = VideoInfo::CS_YV12; // RGB would be CS_BGR32 -------- dest_frame = env->NewVideoFrame(vi); dest_data = dest_frame->GetWritePtr(); dest_pitch = dest_frame->GetPitch(); dest_height = dest_frame->GetHeight(); -------- 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; ------- unsigned int x, y; for (y = 0; y < src_height; ++y) { for (x = 0; x < src_row_size; ++x) { dest_data[x] = src_data[x] + 1; } src_data += src_pitch; // dest_data -= dest_pitch; // decrement in the case of RGB dest_data += dest_pitch; } return dest_frame; -------- colorbars(pixel_type="YV12") Myplugin(mode=0) Thanks p.s. using avisynth+, if that makes any difference. Last edited by jmac698; 18th August 2014 at 15:09. |
14th August 2014, 21:03 | #2 | Link |
unsigned int
Join Date: Oct 2012
Location: 🇪🇺
Posts: 760
|
It's because you're not copying the chroma planes at all.
You need to do what you're doing two more times: for PLANAR_U and PLANAR_V. Of course you can't keep calling GetWritePtr, GetPitch and GetHeight without parameters like you do there because you'll end up copying the chroma over the luma, or something. You have to pass PLANAR_Y, etc to those functions as well.
__________________
Buy me a "coffee" and/or hire me to write code! |
15th August 2014, 08:56 | #5 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
All the Y* formats are planar, except for YUY2.
See http://avisynth.nl/index.php/Filter_SDK/Data_storage. |
18th August 2014, 12:45 | #6 | Link |
Registered User
Join Date: Jan 2006
Posts: 1,867
|
So I fixed that, now I'm getting random pixel garbage in my output which varies by frame. What could cause that?
https://www.sendspace.com/file/58l5o5 |
18th August 2014, 14:00 | #8 | Link |
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 |
18th August 2014, 14:23 | #9 | Link | |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
Quote:
You need to uncomment the earlier code which initialises it explicitly. Also, to allow for YUY2 source, x needs to be incremented by src_inc rather than via x++ in the inner loop. |
|
Thread Tools | Search this Thread |
Display Modes | |
|
|