id	summary	reporter	owner	description	type	status	priority	component	version	resolution	keywords	cc	blockedby	blocking	reproduced	analyzed
773	Decoding H.264 gets stuck with Win XP, w32threads, and custom AVCodecContext.get_buffer	andreasg		"I have an application that decodes H.264 video to in-memory RGB frames.  It works fine multi-threaded in Windows 7 or single-threaded in Windows XP.  I use FFmpeg 0.9 that includes the patches from Dec. 7 of this functionality in w32threads.h.

FFmpeg is cross-compiled from Fedora 15 with this configuration:

configure --enable-memalign-hack --disable-pthreads --enable-w32threads --arch=x86 --target-os=mingw32 --cross-prefix=i686-pc-mingw32-

I traced the problem to my use of a custom get_buffer, the functions ff_thread_get_buffer and submit_packet, and the new w32threads implementation for Windows XP (not using SleepConditionVariableCS).

After decoding some of the frames, the threads get stuck here:

ff_thread_get_buffer:
while (p->state != STATE_SETTING_UP)
    pthread_cond_wait(&p->progress_cond, &p->progress_mutex);

submit_packet:
while (p->state == STATE_SETTING_UP)
    pthread_cond_wait(&p->progress_cond, &p->progress_mutex);

As the ffmpeg application does not use a custom get_buffer, it does not have this problem.  I tried to figure out what is happening in w32threads.h but unfortunately adding too many print statements makes the problem go away.

I think that the problem can be avoided by using different condition variables for signaling in the two directions between the threads but I haven't tried it.

P.S.: I'm using a custom get_buffer to get a more reliable presentation timestamp.  I should check if this is still necessary in the current FFmpeg version.

  int64_t global_video_pkt_pts = AV_NOPTS_VALUE;

  int getFrameBuffer (AVCodecContext* c, AVFrame* pic) {
    int ret = avcodec_default_get_buffer (c, pic);
    int64_t* pts = (int64_t*) av_malloc (sizeof (int64_t));
    *pts = global_video_pkt_pts;
    pic->opaque = pts;
    return ret;
  }

  void releaseFrameBuffer (AVCodecContext* c, AVFrame* pic) {
    if (pic)
      av_freep (&pic->opaque);
    avcodec_default_release_buffer (c, pic);
  }

  ...
  global_video_pkt_pts = packet_context.packet.dts;
"	defect	closed	normal	avcodec	0.9	needs_more_info					0	0
