View Full Version : Problems with assignment of PVideoFrame
vcmohan
12th November 2006, 09:38
I have tried assigning PVIdeoFrame and got Access write errors.
On checking I found that after assigning the Read pointer is correctly received but the write pointer is probably null. The pitch values however are correctly reported. The code portion I used is
PVideoFrame __stdcall VarianSlim::GetFrame(int in, IScriptEnvironment* env)
{
int n, nframes;
PVideoFrame IFrame = child->GetFrame(in, env);
if(in<StartFrame ||in>EndFrame )
return IFrame;
n=in-StartFrame;
nframes= EndFrame-StartFrame; // actual intervals
const int bwd = vi.width;
const int bht = IFrame->GetHeight();
int kb = vi.BitsPerPixel()/8;
PVideoFrame work1 = env->NewVideoFrame(vi);
PVideoFrame Frame, work, work2;
// the following two lines were inserted for debugging
const unsigned char* f1p = IFrame->GetReadPtr();
unsigned char *w1p = work1->GetWritePtr();
Frame = IFrame;
work = work1;
const unsigned char* fp = Frame->GetReadPtr();
const int fpitch = Frame->GetPitch();
unsigned char *wp = work->GetWritePtr();
const int wpitch = work->GetPitch();
// my debugging tool
env->ThrowError("fpdif %d, wpdif %d,fpitch %d, wpitch %d",
f1p - fp, w1p - wp,fpitch,wpitch);
I get fpdif as 0 correctly. But wpdif is a huge number suggesting that wp is probably null. fpitch was 7632 and wpitch 1600. These are correct as I am processing immediately after crop.
What is the error in this type of assignment?
foxyshadis
12th November 2006, 10:06
Calling GetWritePtr twice will give you two different frames - it on;y allows a single write reference. Avisynth assumes you will want to write two frames from the same template, and allocates a new cache slot for that. You have to reuse the same writeptr if you want to keep scribbling directly onto the frame. And it's even worse if the clip is accessed by another filter. (You might as well always use NewVideoFrame unless a memory copy is just too much overhead. Plays nicer with the cache, keeps the weirdness down.)
vcmohan
12th November 2006, 13:16
Calling GetWritePtr twice will give you two different frames -
No I have put that call above only to check. I am not calling write pointer twice. I am only assigning work to work1 and then calling wp = work->GetWritePtr() in my actual code. That gave me an access violation. So I put those two lines to debug.
Even if Avisynth produces a different frame, I should not get access violation as I would be writing to a valid new frame.
The call after assignment of frame apparently gave a null pointer. Otherwise I would not have got the access error.
IanB
13th November 2006, 00:15
@vcmohan, PVideoFrame work1 = env->NewVideoFrame(vi);
PVideoFrame Frame, work, work2;
unsigned char *w1p = work1->GetWritePtr(); // Works! (ref is 1)
work = work1; // Inc's ref count!
unsigned char *wp = work->GetWritePtr(); // Will return null, (ref is 2)@foxyshadis, fudd!, read the code again! You are thinking of MakeWriteable.
vcmohan
13th November 2006, 03:45
I think you have not fully appreciated my problem. My original code was without those two lines which were inserted later for checking. My original code was
[code]
PVideoFrame __stdcall VarianSlim::GetFrame(int in, IScriptEnvironment* env)
{
................
PVideoFrame IFrame = child->GetFrame(in, env);
...............
PVideoFrame work1 = env->NewVideoFrame(vi);
PVideoFrame Frame, work, work2;
Frame = IFrame;
work = work1;
const unsigned char* fp = Frame->GetReadPtr();
const int fpitch = Frame->GetPitch();
unsigned char *wp = work->GetWritePtr();
const int wpitch = work->GetPitch();
[code]
This gave me access write violation and from the very small address value I could guess that I am trying to write using a null pointer. Why should I get this error?
tritical
13th November 2006, 04:47
PVideoFrame __stdcall VarianSlim::GetFrame(int in, IScriptEnvironment* env)
{
................
PVideoFrame IFrame = child->GetFrame(in, env);
...............
PVideoFrame work1 = env->NewVideoFrame(vi); // vf refcount incremented to 1
PVideoFrame Frame, work, work2;
Frame = IFrame;
work = work1; // vf recount incremented to 2
const unsigned char* fp = Frame->GetReadPtr();
const int fpitch = Frame->GetPitch();
unsigned char *wp = work->GetWritePtr(); // returns null because vf refcount>1
const int wpitch = work->GetPitch();
GetWritePtr checks IsWriteable(), which requires that both the vfb refcount and the vf refcount are 1. In this case the vfb refcount is probably 1, so a debug build would get past the assert(). However, IsWriteable would return false because the vf refcount is > 1... so then GetWritePtr returns a null pointer.
foxyshadis
13th November 2006, 07:18
@foxyshadis, fudd!, read the code again! You are thinking of MakeWriteable.
You're right, I was. ;_;
vcmohan
14th November 2006, 05:01
[code]
GetWritePtr checks IsWriteable(), which requires that both the vfb refcount and the vf refcount are 1. In this case the vfb refcount is probably 1, so a debug build would get past the assert(). However, IsWriteable would return false because the vf refcount is > 1... so then GetWritePtr returns a null pointer.
Thanks for explaining why this error occurs. I would like to know how I can get out of this. I tried using work = &work1. But this was not acceptable. Ofcourse right now I am using the more cumbersome assignment of pointers, pitches etc.
IanB
14th November 2006, 06:38
Perhaps you had better tell us what you are trying to do.
Why do you think you need multiple concurrent references to a VideoFrame object. Hording VideoFrames is a big no no! Probably you should be remembering the frame number and child object and child->GetFrame(in, env) whenever you need it.
To release a PVideoFrame reference assign null or another VideoFrame to it.
vcmohan
15th November 2006, 04:25
Perhaps you had better tell us what you are trying to do.
Why do you think you need multiple concurrent references to a VideoFrame object.
I process the input frame and have two work frames. Depending upon the results of processing may need to iterate more. The input of one becomes output and output becomes input. So I can not ask for more newvideoframes as I would lose data. Assigning a long list of pointers is the way I am going about now. I have also to assign the work1 or work2 to the output work. Also the colors RGB or YUV planes need not come from same input. I keep track and finally I will patch up.
I am not calling the input frame again and again. I thought assigning frames will be simplest but it came out as unworkable due to writeptrs becoming null.
May be I should not use the newvideoframe and have my own buffers.
Thanks for the inputs
squid_80
15th November 2006, 11:40
Going from what IanB said:
To release a PVideoFrame reference assign null or another VideoFrame to it.
When you assign one frame to another, for example work = work1;, isn't it trivial to follow it with work1 = NULL;? Or work1 = some_other_PVideoFrame; which seems more suited to your explanation.
IanB
16th November 2006, 02:23
Still not 100% sure what you are really trying to do, perhaps posting some source code will make things clearer.
But heres an idea, make a local array of PVideoFrame's and remember and track the indexes in your processing. The important idea is to only have exactly 1 reference to any PVideoFrame you want to write to. PVideoFrame frames[2];
frames[0] = child->GetFrame(in, env);
env->MakeWriteable(&frames[0]);
frames[1] = env->NewVideoFrame(vi);
IFrame=0;
work = 1;
...
srcp = frames[IFrame]->GetReadPtr();
...
dstp = frames[work]->GetWritePtr()
...
work1 = work;
work = IFrame;
...
vcmohan
16th November 2006, 04:38
[QUOTE=IanB;900881] The important idea is to only have exactly 1 reference to any PVideoFrame you want to write to.[code]
Yes I am doing this now. I thought I could get the write pointers at a later stage also (after I assign frames)but now I understand that doing so will result in getting a null. Since I remember to having no such problem when I called repeatedly write ptr of U or V planes, I had this confusion.
Thanks for clearing my doubts.
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.