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.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Development
Register FAQ Calendar Today's Posts Search

Reply
 
Thread Tools Search this Thread Display Modes
Old 28th August 2015, 12:44   #1  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,316
Question about source and destination in pluggin

I'm wondering something, because of VDub pluggin behavior.

In VDub pluggin, there is the FILTERPARAM_SWAP_BUFFERS parameter. If you use it, memory storage for source and destination will be differents.
If you don't, source and destination pointers will be the same.

How avisynth behave, when i'm doing something like this :
Code:
PVideoFrame __stdcall AutoYUY2::GetFrame(int n, IScriptEnvironment* env) 
{
	PVideoFrame src = child->GetFrame(n,env);
	PVideoFrame dst = env->NewVideoFrame(vi);
	uint8_t *dstp = dst->GetWritePtr(PLANAR_Y);
	const uint8_t *srcYp = src->GetReadPtr(PLANAR_Y);
jpsdr is offline   Reply With Quote
Old 28th August 2015, 15:29   #2  |  Link
TurboPascal7
Registered User
 
TurboPascal7's Avatar
 
Join Date: Jan 2010
Posts: 270
Surprisingly enough, NewVideoFrame returns a new video frame. With its own buffers and everything.
__________________
Me on GitHub | AviSynth+ - the (dead) future of AviSynth
TurboPascal7 is offline   Reply With Quote
Old 28th August 2015, 17:52   #3  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,316
Quote:
Originally Posted by TurboPascal7 View Post
Surprisingly enough, NewVideoFrame returns a new video frame. With its own buffers and everything.
What a surprise indeed

jpsdr is offline   Reply With Quote
Old 29th August 2015, 12:41   #4  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
With GetFrame() you need to use env->MakeWritable(&dst); before any writing (EDIT: Creates new frame and blits the contents of frame into the new writable one), best used where you are modifying just selected pixels or channels.
NewVideoFrame is already writable but you need to render all channels with valid data.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 29th August 2015 at 12:44.
StainlessS is offline   Reply With Quote
Old 30th August 2015, 10:13   #5  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,316
In my case, colorspace change, so using NewVideoFrame is obviously the correct way.
In case you eventualy don't need to create a new frame, i assume somthing like this would be the correct way :
Code:
PVideoFrame __stdcall AutoYUY2::GetFrame(int n, IScriptEnvironment* env) 
{
	PVideoFrame frame = child->GetFrame(n,env);
	const uint8_t *src = frame->GetReadPtr(PLANAR_Y);
           env->MakeWritable(&frame);
           uint8_t *dst=frame->GetWritePtr(PLANAR_Y);
Is this the only way, and it always works the same way (creates a new memory and duplicate), or is there also a way to work the same than VDub pluggin, having finaly src and dst the same (avoiding the time and ressources to allocate new memory and transfer data) and somthing like the FILTERPARAM_SWAP_BUFFERS of VDub pluggin is also avaible on avisynth ?

Last edited by jpsdr; 30th August 2015 at 10:15.
jpsdr is offline   Reply With Quote
Old 30th August 2015, 12:16   #6  |  Link
foxyshadis
Angel of Night
 
foxyshadis's Avatar
 
Join Date: Nov 2004
Location: Tangled in the silks
Posts: 9,559
MakeWritable already works like vdub! The dest buffer is the same as source and you'd better keep track. It's NewVideoFrame that is the standard way that creates an entirely new canvas for you to write on.

But seriously, it's 2015. Memory is in vast supply and you can memory transfer one to two thousand frames a second at 1080p. Why would you ever need to use MakeWritable unless you're making a simple, small change to an existing image? Any full-frame processing would be better off writing to a new buffer to eliminate any possibility of bugs. (For instance, your idea of stride may not be the same as the buffer's.)
foxyshadis is offline   Reply With Quote
Old 1st September 2015, 09:47   #7  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,316
Don't want to open another thread, more or less related...

If i want to know the size of the whole frame, should be multiplanar or not, is vi.BMPSize() the size of the whole frame ?
If not, what is it ? I've not been able to see anything else that could provide this information in the avisynth.h.
jpsdr is offline   Reply With Quote
Old 1st September 2015, 14:50   #8  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,980
From Wiki here: http://avisynth.nl/index.php/Filter_..._API/VideoInfo
Code:
int BMPSize() const;

For interleaved formats it will return the size of the frame in bytes where the width is rounded up to a multiple of 4 bytes. 
For planar formats it will do the same but only for the first plane. So, it's the number of bytes of a frame as it was a BMP frame.

examples:

640x480 RGB24: BMPSize() = 480 * 3*640 = 921600
643x480 RGB24: BMPSize() = 480 * 3*644 = 927360

640x480 YV24: BMPSize() = 480 * 640 = 307200
643x480 YV24: BMPSize() = 480 * 644 = 309120

Since v5 the behavior for planar formats is the same as for interleaved formats.
From Source v2.6 Final:
Code:
// struct VideoInfo
  &VideoInfo::BMPSize,                      //   int     (VideoInfo::*BMPSize)() const;
Also baked as COMMENT (VERSION 3 header), from v2.6 Interface.cpp
Code:
/* Baked ********************
bool VideoInfo::IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); }  // Don't use this
int VideoInfo::BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); }   
    // Will not work on planar images, but will #return only luma planes
    
int VideoInfo::RowSize() const { return BytesFromPixels(width); }  // Also only returns first plane on planar images
int VideoInfo::BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p;  } return height * ((RowSize()+3) & ~3); }
__int64 VideoInfo::AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; }
   Baked ********************/
Again from v2.6 Interface.cpp
Code:
int VideoInfo::BMPSize() const {
  if (!IsY8() && IsPlanar()) {
    // Y plane
    const int Ybytes  = ((RowSize(PLANAR_Y)+3) & ~3) * height;
    const int UVbytes = Ybytes >> (GetPlaneWidthSubsampling(PLANAR_U)+GetPlaneHeightSubsampling(PLANAR_U));
    return Ybytes + UVbytes*2;
  }
  return height * ((RowSize()+3) & ~3);
}
EDIT: A bit more from Interface.cpp
Code:
int VideoInfo::RowSize(int plane) const {
  const int rowsize = BytesFromPixels(width);

  switch (plane) {
    case PLANAR_U: case PLANAR_V:
      return (!IsY8() && IsPlanar()) ? rowsize>>GetPlaneWidthSubsampling(plane) : 0;

    case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED:
      return (!IsY8() && IsPlanar()) ? ((rowsize>>GetPlaneWidthSubsampling(plane))+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) : 0; // Aligned rowsize

    case PLANAR_Y_ALIGNED:
      return (rowsize+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize
  }
  return rowsize;
}

...

int VideoInfo::GetPlaneWidthSubsampling(int plane) const {  // Subsampling in bitshifts!
  if (plane == PLANAR_Y)  // No subsampling
    return 0;
  if (IsY8())
    throw AvisynthError("Filter error: GetPlaneWidthSubsampling not available on Y8 pixel type.");
  if (plane == PLANAR_U || plane == PLANAR_V) {
    if (IsYUY2())
      return 1;
    else if (IsPlanar())
      return ((pixel_type>>CS_Shift_Sub_Width)+1) & 3;
    else
      throw AvisynthError("Filter error: GetPlaneWidthSubsampling called with unsupported pixel type.");
  }
  throw AvisynthError("Filter error: GetPlaneWidthSubsampling called with unsupported plane.");
}

...

int VideoInfo::GetPlaneHeightSubsampling(int plane) const {  // Subsampling in bitshifts!
  if (plane == PLANAR_Y)  // No subsampling
    return 0;
  if (IsY8())
    throw AvisynthError("Filter error: GetPlaneHeightSubsampling not available on Y8 pixel type.");
  if (plane == PLANAR_U || plane == PLANAR_V) {
    if (IsYUY2())
      return 0;
    else if (IsPlanar())
      return ((pixel_type>>CS_Shift_Sub_Height)+1) & 3;
    else
      throw AvisynthError("Filter error: GetPlaneHeightSubsampling called with unsupported pixel type.");
  }
  throw AvisynthError("Filter error: GetPlaneHeightSubsampling called with supported plane.");
}
EDIT: Its not usually necessary to know the full size of frame, frame could be cropped in-situ.
Also note, pitch can change at every frame due to eg crop and interleave.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 1st September 2015 at 15:05.
StainlessS is offline   Reply With Quote
Old 1st September 2015, 15:00   #9  |  Link
jpsdr
Registered User
 
Join Date: Oct 2002
Location: France
Posts: 2,316
Ok, thanks.
jpsdr is offline   Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 10:32.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.