Link to home
Start Free TrialLog in
Avatar of erik_nodland
erik_nodlandFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Need help with a weird problem I can't fix

Hi All,

I have an application that accepts audio data every 20ms. I decode the data and write it to disk. The problem is that I am getting corrupt data when I include some lines of code. Below will explain what I mean. Ultimately what I want to do is decode both inbound and outbound streams and mix them before writing. The trouble is as soon as I try and decode the ourbound stream something gets screwed.
See comments below:

            byte[] InboundG729L1 = new byte[10], InboundG729L2 = new byte[10];
            byte[] OutboundG729L1 = new byte[10], OutboundG729L2 = new byte[10];
            short[] InboundDecodedG729L1 = new short[80], InboundDecodedG729L2 = new short[80];
            short[] OutboundDecodedG729L1 = new short[80], OutboundDecodedG729L2 = new short[80];
            short[] inbound = new short[160], outbound = new short[160];
            short result = 0;
            byte retval;

            //Copy both halves of the RTP data into seperate arrays
            Buffer.BlockCopy(inboundRTP.RTPPayload, 0, InboundG729L1, 0, 10);
            Buffer.BlockCopy(inboundRTP.RTPPayload, 10, InboundG729L2, 0, 10);
           
            Buffer.BlockCopy(outboundRTP.RTPPayload, 0, OutboundG729L1, 0, 10);
            Buffer.BlockCopy(outboundRTP.RTPPayload, 10, OutboundG729L2, 0, 10);
           
            //Decode first half of data
            IntPtr p = Global.decode(InboundG729L1);
            Marshal.Copy(p, InboundDecodedG729L1, 0, 80);
            Global.freemem(p);

            //Decode second half of data
            p = Global.decode(InboundG729L2);
            Marshal.Copy(p, InboundDecodedG729L2, 0, 80);
            Global.freemem(p);

//****** If I uncomment the following 3 lines the data comes out corrupted. It is fine as long as they remain commented
//****** As you can see the 3 lines shouldn;t have any effect on what I am writing to disk.
//****** Ultimately I want to use the decoded output from below to mix both streams together.
            //p = Global.decode(OutboundG729L1);
            //Marshal.Copy(p, OutboundDecodedG729L1, 0, 80);
            //Global.freemem(p);
           
            //Copy both arrays of decoded data into one array ready to write to disk
            Buffer.BlockCopy(InboundDecodedG729L1, 0, inbound, 0, InboundDecodedG729L1.Length * 2); //Multiply by 2 because it is a byte offset and we are dealing with 16bits
            Buffer.BlockCopy(InboundDecodedG729L2, 0, inbound, 160, InboundDecodedG729L2.Length * 2);

            for (int i = 0; i < 160; i++)
            {
                byte wByte = inbound[i];
                bw.Write(wByte);
            }
}

The decode function is declared as

[DllImport("decoder.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern IntPtr decode([MarshalAs(UnmanagedType.LPArray, SizeConst = 10)]byte[] bArray);

The function in c++ looks like

extern "C" __declspec(dllexport) short * __stdcall decode(unsigned char serial[L_FRAME_COMPRESSED])
{

      int bfi=0;
      short * retval = new short[80];
      
      va_g729a_decoder(serial, retval, bfi);
      
      return retval;
}

Any help on this one would be appreciated
Thanks,
Erik
ASKER CERTIFIED SOLUTION
Avatar of 2266180
2266180
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of erik_nodland

ASKER

Hi,

Thanks for the response. I have checked the timings and the whole process is around 2ms and it is all in a single thread.

Also, not sure what you mean by decoding inboundg729L1 twice? I first decode InboundG729L1, then decode InboundG729L2. The commented lines decode OutboundG729L1, not InboundG729L1?
Could it be a pointer issue of some king courupting memory?

Many thanks,

Erik
ups, you are right. I was looking at the numbers only :D my bad.

I'm not into sound and otehr stuff like that, but the memory the pointer is pointing to was allocated and filled, right? because if it wasn't filled then it is the reason for the bad data resulted.

I am thinking that one way to check is to save that memory data (outbound) to disk and see if it's ok. then, in another application that you will only use for debugging :), decode that file content and see if it decodes ok.

that's what I can think of for the moment. I'll get back to you if needed in the morning.

cheers
Hi,

OK mate, thanks again. I will have another play around and let you know what I come up with :-)

cheers,

Erik
ok. and don't forget to make sure that indeed you have valid data in the OutboundG729L1 ;)
Ok. All data being returned looks to be valid. I saved the inbound stream to disk and that was fine. I saved the outbound stream to disk and that was fine also. But if I decode both streams and then do nothing more than save one of the streams to disk I get corruption. I compared the results of the two files and interestingly it seems that the first iteration is fine. IE the first 160 bytes is the same in both files after that it gets corrupted. BTW, the corruption isn't that bad that I can;t make out the audio. It just sounds very tinny and echoy?

I just can;t figure this out. It is driving me crazy.

Is there a workaround you can think of? Another way of calling the DLL perhaps?

cheers,

Erik
well ... the dll calling looks ok.

what I am thinking now is that maybe the outboubd is not encoded with the same algorithm or the same way as the inbound. are you sure that they are encoded the same way?
also, is the inboud supposed to be the same as the outbound?

also, is one of the inboud/outbound data encoded/decoded depending on the other? meaning that for example outbound depends on inboud or viceversa.


also, just so that I understand the process: what is inboud and what is outbound? like, inboud is comming from a device and outbound is going to the sound card or how am I suppose to relate those 2?

thanks
Hi,

Outbound and Inbound are both processed identically. What doesn;t make sense is that for the moment I am not doing anything with outbound. Merely the process of passing it to the dll and decoding it is enough to make the inbound object corrupt?

inbound object is an inbound rtp stream and outbound is the ourbound rtp stream from an IP phone. For some reason decoding the outbound object is somehow corrupting the inbound object even though they are totally seperate?

thanks again for your help,

Erik
I don't know how the whole thing is working, but I'm just thinking: is it possible that whn reading the outboud, the "cursor" of the inboud is progressing? what I am thinking about is that reading the outbound has the same effect as reading from a file: something gets changed that affects the input.

try this:
- if you save the outbound to a file (meaning that it is processed), does the inbound get corrupted just like in the case you decode the outbound? if so, my guessing might be correct.
if not, then try this:
- copy the outbound data not to file but to another memory location, and decode that memory location. is the inbound still getting corrupted? if not, then again my guessing might be correct, if yes, considering the case in which we are, I am lost :)

but before all that, I just took another look over the code and have a few issues understanding the requirements:
wasn't the following block of code
            //Copy both arrays of decoded data into one array ready to write to disk
            Buffer.BlockCopy(InboundDecodedG729L1, 0, inbound, 0, InboundDecodedG729L1.Length * 2); //Multiply by 2 because it is a byte offset and we are dealing with 16bits
            Buffer.BlockCopy(InboundDecodedG729L2, 0, inbound, 160, InboundDecodedG729L2.Length * 2);

actually be:

            //Copy both arrays of decoded data into one array ready to write to disk
            Buffer.BlockCopy(InboundDecodedG729L1, 0, inbound, 0, InboundDecodedG729L1.Length * 2); //Multiply by 2 because it is a byte offset and we are dealing with 16bits
            Buffer.BlockCopy(InboundDecodedG729L2, 0, inbound, InboundDecodedG729L1.Length * 2, InboundDecodedG729L2.Length * 2);

then I'm guesing there might also be some kind of issues with the outbound since the outbound is 80 before decoding and not 10 as the inbound, and maybe you have done some mistakes when copy-pasting :) just a possibility
so you should get over the code and make sure that everything is correct ;)

cheers
Hi,

Tried all sorts of things. In the end I found a workaround by simply creating a second C++ DLL and then used that for the inbound. Must have something to do with initialising the decode or something.

Anyway thanks for all your help. Full points.
weird indeed :)
that possibility didn't even occure to me... hm.. have to open my eyes more widely next time :)