This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DM642 Video Port / EDMA: can I do frame decimation?

 

I am using the 642's video port to suck in raw RGB data (24-bit) whose source is a VGA display signal running 1024x768@60 Hz.  I am using a TI codec to resize and then encode these frames (.h264). As you can imagine, I can't compress frames at 60 FPS, so I would like to be able to decimate by dropping frames on the ground while I am processing a given frame. I can't use a vanilla ping-pong approach because I can't spare the memory BW...I really just want to dump frames into the bit bucket.

The problem is that I want to run the video port in "continuous mode" if possible so that I can get the next frame as quickly as possible when I am ready (as opposed to one-shot mode that has to re-acquire via 2 vertical syncs).  In continuous mode, the video port will be raising the EDMA event associated with the video data (which currently is raised after every row is captured).  So the challenge is: keep the video port running continuously, raising EDMA events, but also drop frames on the ground via EDMA.

I think this would be quite easy to do if there were the idea of a "dummy" EDMA transfer; i.e. the EDMA row event gets raised, but I just send the row data to nowhere...essentially, what I really want to do is simply clear the FIFO when the EDMA events happen while I am in "dropping" mode.  But I can't seem to make the EDMA do this....I think it wants to send data somewhere valid every time, which is just a waste of effort when I want to drop.

The way that I would do this if I could:

1. On first frame, transfer whole frame to RAM using EDMA xfer #1 (this is working)....EDMA transfer #1 "links" to a "dummy" EDMA transfer xfer_dummy.

2. Transfer xfer_dummy will simply drop the buffer on the ground if possible, and will simply link to itself. It will raise a transfer complete isr that  will check to see if I am ready to get the next frame; if so, then inside the isr I will link back to xfer #1.

Is this possible?

 

The other way I reasoned that this could be done: is there a way to have an isr execute *instead* of EDMA when the video port EDMA event is raised?  If this were possible, then I could set up this isr upon completion of the first transfer, then have my isr run instead of EDMA on events that represent frames I want to drop, then re-activate the EDMA handling of the event when I am ready...

Any ideas on whether these things are possible?  Have you done anything like this before?

Thanks for any help!

Steve

  • Titus said:
    1. On first frame, transfer whole frame to RAM using EDMA xfer #1 (this is working)....EDMA transfer #1 "links" to a "dummy" EDMA transfer xfer_dummy.
    2. Transfer xfer_dummy will simply drop the buffer on the ground if possible, and will simply link to itself. It will raise a transfer complete isr that  will check to see if I am ready to get the next frame; if so, then inside the isr I will link back to xfer #1.
    Is this possible?

    It certainly looks possible.  Upon initial inspection I don't see any issues.

  • Brad,

    Thanks, but do you know of a way to implement the "dumping on the ground" EDMA transfer? I need to essentially just clear the FIFO and not send the data anywhere, because I don't want to eat any memory bandwidth unnecessarily...this is what I don't know how to do...

  • Ok, I guess I did not precisely understand your meaning in "dumping on the ground".  As I see it you have 2 options:

    1) Use EDMA to service video ports and write them to a "throw away buffer".  This will of course consume some memory bandwidth.

    2) Use CPU to read video port.  That way you can do the read but are not forced to put it anywhere.

    Personally I think the first option will be much better.  Although it will consume some memory bandwidth I imagine the overall impact will be far less than having the CPU do the reads.

  • Brad,

    I have already implemented #1 and it looks like it is working, but it is far from ideal since I have an encoder working downstream that really wants to chew up all the resources I have wrt memory, cache, etc.

    I have entertained a couple other ideas while banging my head on this problem...I was wondering if you could comment on these (may be helpful to others as well);

    1. I tried to use the BLKCAP capability, which looks on the surface to be just what the doctor ordered (see section 3.11.1 of SPRU629F).  With this approach, I do the following:
        a. Video Port is in continuous mode (RAW).  Set up an initial DMA transfer to transfer my first frame to DRAM...but this transfer links to nothing.
        b. Setup a handler for FIFO overrun: this handler sets BLKCAP for the port/channel in question, then clears it.  According to SPRU629F, when the capture is re-enabled we will wait in raw mode until the next frame comes in to resume capture, which is exactly what I want. In between setting and clearing BLKCAP, I reset the EDMA params so that on NEXT transfer, data will go to DRAM.

       The flow in this case should be as follows:  1) cap frame 1,   2) second line of frame 2 will cause overflow, which will block, then re-enable capture,  3) frame 3 should be caught normally.  The effect of this is to decimate by every other frame, and is flexible; i.e. I can just count "dropped" frames while capture is blocked and then re-enable when I have dropped, say, a specified number of frames.

    This ALMOST works. The problem is that when I re-enable capture by clearing BLKCAP, it misses the next frame and gets the subsequent one -- this means this method can only decimate by a factor of 3.  I am checking now whether I can do 3,4,5...  or whether I am limited to 3,6,9.   Anyway, it doesn't make sense to me why I miss that next frame -- after all, there is an eternity of time until that frame arrives, since the overflow occurs on the second line!

     

    2. I am going to try the idea you suggest in #1, but without the memory hit, by dumping to an unused output port (some GPIO memory mapped pin or unused peripheral port). Will this work?  Will this save me the memory BW?

     

    Thanks,

    Steve

     

  • I'm not sure on the BLKCAP.  For the second item you mention, you might want to try writing to L2 SRAM.  You can setup the indexing such that it's writing to the same 32-bit location over and over such that you're not consuming precious internal memory.  (I recommend declaring 128 bytes of "dummy memory" for dumping the data, because otherwise the EDMA write to L2 will cause that line to be invalidated over and over which might affect accesses to other variables.)  Writes to peripheral space are generally slow, which is why I think writing to internal memory would be better.  Same goes for writes to external memory, i.e. they are "slow" compared to internal memory. 

  • Titus,

    Writing to a peripheral in Config Space is a really bad idea because it will be extremely slow.

    For writing the the data to a bit-bucket, here are some ideas:

    • This one does not count, but if you were using one of the EDMA3 devices then you could just write to an unsupported address and the write command would just get thrown away. The read would run but the write would disappear. It would be nice to find similar results for EDMA2, but no promises.
    • If you are not using a video output port, maybe you could write to one of those. It would be just as wide and would be a faster port than a GPIO register or such. You might have to simply make sure no error interrupts would get generated or that the video output port will not mind being written to when not in use.
    • Try writing to very coarse non-existent memory ranges like 0x40000000 or 0xc0000000. Important caveat: these are reserved and TI will not guarantee what will happen when you write here, so you are not supposed to write here. But if you try it and do not notice anything going wrong, for that one chip you are okay. I cannot promise how a reserved region will operate from chip-to-chip or over any conditions. And I may get my hand slapped for suggesting it, so don't tell anyone I did.
    • Maybe you would write to the same video port you are reading from. It ought to be disabled from any real functionality, but again I have not tested it.

    To figure out if any of these are good ideas, you will need to have a way to measure the time it takes to run EDMA copies from the video port to various addresses. And you also might need to be able to test that under the other memory BW loads that you are worrying about.