Counting frames in a video source

Store Forums Video Experimenter General Discussion Counting frames in a video source

Viewing 15 posts - 1 through 15 (of 15 total)
  • Author
    Posts
  • #723
    zivilyn861
    Member

    Hello,

    First of all, I very much appreciate the effort that’s gone into the Video Experimenter! It’s allowed me to get a quick-and-dirty proof of concept done for what would have otherwise taken quite a bit of time. I’ve already searched on the forum for someone asking a similar question but have found nothing; my apologies if it’s already been brought up.

    Basically, I just want to count the number of full frames in a composite video signal. I have a video signal coming from a handful of sources, and I’d like to know precisely how many frames have elapsed, keeping a running total of them over a period of time. I’ve dug around in the modified TVout library as well as handful of similar example projects but haven’t found a precise way of doing this.

    First, is it possible to do what I’m asking? I’m fooling around with some TVout internals (for example, how millis() is implemented), but I’m not quite there yet. Any help would be appreciated.

    Thanks!

    #2049
    Michael
    Keymaster

    There is a function pointer called vbi_hook that runs every time a frame ends (in the vertical blanking interval). You can define a function for the vbi_hook and increment a counter in it. If you want to access the counter value from outside an interrupt service routine (e.g. to display it), make sure you declare your counter variable as volatile.

    Or you can increment your counter in the ISR that runs every time a new frame starts: [tt:3j0g3aqq]ISR(TIMER1_OVF_vect)[/tt:3j0g3aqq]
    All this code is in [tt:3j0g3aqq]video_gen.cpp[/tt:3j0g3aqq]

    #2051
    zivilyn861
    Member

    Ah, perfect! Thank you very much!

    #2053
    zivilyn861
    Member

    I’m having a bit of an issue that maybe you can help clarify a bit more.

    I’ve tried both methods you’ve mentioned (incrementing a volatile int/unsigned long within either ISR(TIMER1_OVF_vect) or a function that I set the *vbi_hook() function pointer to) with some unexpected results. As you suspected, my goal is to display a running total of frames elapsed via an overlay. I have a function that accesses the volatile variable within TVout.cpp so that my sketch can sprintf it to the overlay.

    The issue I’m having is that, while I can easily set the frameCount variable to a static number, I’m having issues with it when I try an increment. For example, inside of the ISR(TIME1_OVF_vect) function, a frameCount++; statement ends up displaying “42” as the framecount, and that count doesn’t change.

    Both methods more or less produce the same results. I suspect I’m missing something really simple here–can you help?

    Thanks!

    #2054
    Michael
    Keymaster

    Can you show us your code in the main loop()? Are you refreshing the display of frameCount over and over? You need to keep drawing it to keep the display updated.

    #2056
    zivilyn861
    Member

    Certainly, below is what I’m using for my loop().


    void loop() {
    sprintf(s, "Frames: %d", tv.count_frames());
    tv.print(0, 0, s);
    }

    As a simple test, that’s all I’m printing. For what it’s worth, I’m using the OverlayDemo code as a baseline. In thise case, count_frames() is implemented as such in TVout.cpp:


    int TVout::count_frames() {
    return frameCount;
    }

    That goes back to a volatile int frameCount in video_gen.cpp.

    #2059
    Michael
    Keymaster

    Ok, I may have told you the wrong ISR to increment the frame count. Try doing it in

    ISR(INT0_vect) {
    display.scanLine = 0;
    frameCount++;
    }

    This function should be in your sketch, so you should not have to change TVout.cpp at all. Your sketch can declare

    volatile unsigned long frameCount = 0;

    And loop() can use it directly. Note the format for an unsigned long is “%lu” (I think)

    void loop() {
    sprintf(s, "Frames: %lu", frameCount);
    tv.print(0, 0, s);
    }
    #2060
    zivilyn861
    Member

    Thank you, that worked for getting the number to update on the display. It looks like the INT0 interrupt is hit much more often than a full frame, however. The number gets way too high too quickly. Only incrementing frameCount every 60 (or 64) calls to INT0_vect gets me close to the expected rate, which leads me to believe that this may be called for each line instead of each frame. Judging by the display.scanLine = 0 line, I think that’s what’s happening.

    Perhaps there’s another ISR I can use for it? Otherwise I can simply do some math to make it work out, but it’s technically work the microcontroller shouldn’t be doing in an ISR, so I’d like to make it as accurate and minimally-intensive as possible.

    Sorry for all of the questions, I’m digging into it myself but figured you have a better understanding of the code base in either case.

    Thanks!

    #2061
    Michael
    Keymaster

    This ISR should be called once per frame. You should see it go up by 60 every second. The variable scanLine is which line of the frame it’s on, so when it’s time to start the next frame, we reset the line to 0.

    Is it increasing at a rate higher than 60 frames per second?

    #2062
    zivilyn861
    Member

    Yeah, the counter is increasing by about 5,000 per second. That’s rough timing based on eyeballing it.

    #2063
    Michael
    Keymaster

    Strange. Maybe the ISR fires many times at the beginning of each frame for some reason.
    I’d put the frame increment in your vbi_hook function. (or at the same place in TVout.cpp where the vbi_hook function is called). That definitely should get called once per frame in the vertical blanking interval.

    #2064
    zivilyn861
    Member

    So I went back into the blank_line() function in video_gen.cpp (the only place I’ve seen vbi_hook() called), and incremented there. Strangely, that else if branch doesn’t seem to be getting executed as often as one would think. It’s happening at least once (to set the frameCount), but it’s certainly not being called more than that. I think there’s a bug somewhere where the TVout developer forgot to change some code around. You can tell in the TVout_vid struct that the lines_frame that’s being referenced here has a //remove me comment there, making me think it may have been partially removed at some point. Strangely, hardcoding the comparison to something like _NSTC_LINE_FRAME (which is what lines_frame should be for an NTSC signal) doesn’t do it either.

    For now, I’ve moved my frameCount++ to the if block above that, which seems to occur at the beginning of each frame. That itself gives me a much better (and sane) frame count, albeit technically a small fraction of time off from reality. I’ll dig into the TVout library later to see if I can find the issue.

    Thanks so much for your continued help here; it saved me tons of time.

    #2147
    Michael
    Keymaster

    Regarding the reason why INT0 might be firing much more often than it should, try changing this line:

    EICRA = _BV(ISC11);

    to this:


    EICRA = _BV(ISC01);
    #2221
    tjswift
    Participant

    zivilyn861, did you ever get your code working? I’m just getting started on a project using a Video Experimenter to provide an Uno with the synchronization needed to generate LED blinks to calibrate and/or test a low-light video camera. For starters, I’ll be satisfied starting the LED blink during the vertical blanking interval (VBI), though eventually I’ll want to time it more exactly within a frame or field. I’m getting up to speed on the necessary code, and came across this discussion. I’d appreciate learning how your project worked out

    #8120
    Duncan57
    Participant

    <blockquote=”Michael”>There is a function pointer called vbi_hook that runs every time a frame ends (in the vertical blanking interval). You can define a function for the vbi_hook and increment a counter in it. If you want to access the counter value from outside an interrupt service routine (e.g. to display it), make sure you declare your counter variable as volatile.
    Or you can increment your counter in the ISR that runs every time a new frame starts: [tt:3j0g3aqq]ISR(TIMER1_OVF_vect)[/tt:3j0g3aqq]
    All this code is in [tt:3j0g3aqq]video_gen.cpp[/tt:3j0g3aqq]

    Thank you, it help me so much!!

Viewing 15 posts - 1 through 15 (of 15 total)
  • You must be logged in to reply to this topic.