[FFmpeg-user] execute2 access violation

Robert Nagy ronag89 at gmail.com
Sat Dec 3 13:28:36 CET 2011


I should also mention that I only want to do this for slice threading, not
frame threading.

Basically what I want to achieve is to replace spawning threads and use a
task scheduler instead. This is because my application is very dynamic in
the amount of simultaneous encoders/decoders so with the default
implementation I can end up oversubscribing with ~40 threads.

For this purpose I'm using TBB, which unfortunately does not have a C api.
However, although I seem to follow all the rules for the slice threading
API my implementation fails for certain codecs (dnxhd, h264 etc..), while
works fine with others (prores, mpeg2, ffv2).

As seen from my previous mail, even the most trivial implementation can
fails with some codecs.

int thread_execute(AVCodecContext* s, int (*func)(AVCodecContext *c2, void
*arg2), void* arg, int* ret, int count, int size)
{
    tbb::parallel_for(0, count, 1, [&](int i)
    {
        int r = func(s, (char*)arg + i*size);
        if(ret)
   ret[i] = r;
    });
    return 0;
}

int thread_execute2(AVCodecContext* s, int (*func)(AVCodecContext* c2,
void* arg2, int, int), void* arg, int* ret, int count)
{
    tbb::atomic<int> counter;
    counter = 0;

    assert(tbb::tbb_thread::hardware_concurrency() < 16);
    // Note: this will only work when
tbb::task_scheduler_init::num_threads() < 16, which shouldn't be a problem.
    tbb::parallel_for(tbb::blocked_range<int>(0, count, 2), [&](const
tbb::blocked_range<int> &r)
    {
        int threadnr = counter++;
        for(int jobnr = r.begin(); jobnr != r.end(); ++jobnr)
        {
            int r = func(s, arg, jobnr, threadnr);
            if (ret)
                ret[jobnr] = r;
        }
        --counter;
    });

    return 0;
}

void thread_init(AVCodecContext* s)
{
static const size_t MAX_THREADS = 16; // See mpegvideo.h
static int dummy_opaque;

    s->active_thread_type = FF_THREAD_SLICE;
    s->thread_opaque  = &dummy_opaque;
    s->execute  = thread_execute;
    s->execute2  = thread_execute2;
    s->thread_count  = MAX_THREADS; // We are using a task-scheduler, so
use as many "threads/tasks" as possible.
}

void thread_free(AVCodecContext* s)
{
if(!s->thread_opaque)
return;

s->thread_opaque = nullptr;
}

int tbb_avcodec_open(AVCodecContext* avctx, AVCodec* codec)
{
//CodecID supported_codecs[] = {CODEC_ID_MPEG2VIDEO, CODEC_ID_PRORES,
CODEC_ID_FFV1};

avctx->thread_count = 1;
if((codec->capabilities & CODEC_CAP_SLICE_THREADS) && (avctx->thread_type &
FF_THREAD_SLICE))
thread_init(avctx);
 // ff_thread_init will not be executed since thread_opaque != nullptr ||
thread_count == 1.
return avcodec_open(avctx, codec);
}

int tbb_avcodec_close(AVCodecContext* avctx)
{
thread_free(avctx);
// ff_thread_free will not be executed since thread_opaque == nullptr.
return avcodec_close(avctx);
}


More information about the ffmpeg-user mailing list