Merge commit '90f9a5830b5d332de7ebb1ab45589f1870cbd65d'
authorMichael Niedermayer <michaelni@gmx.at>
Fri, 24 May 2013 10:32:18 +0000 (12:32 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 24 May 2013 11:01:41 +0000 (13:01 +0200)
* commit '90f9a5830b5d332de7ebb1ab45589f1870cbd65d':
  w32pthreads: move from lavc to compat/

Conflicts:
libavcodec/Makefile
libavcodec/pthread.c
libavcodec/vp8.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
Makefile
compat/w32pthreads.h
libavcodec/Makefile
libavcodec/frame_thread_encoder.c
libavcodec/pthread.c
libavcodec/vp8.h
libavformat/network.c

diff --cc Makefile
+++ b/Makefile
@@@ -40,10 -82,9 +40,10 @@@ FFLIBS-$(CONFIG_SWSCALE)  += swscal
  
  FFLIBS := avutil
  
 -DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.avpreset)
 +DATA_FILES := $(wildcard $(SRC_PATH)/presets/*.ffpreset) $(SRC_PATH)/doc/ffprobe.xsd
 +EXAMPLES_FILES := $(wildcard $(SRC_PATH)/doc/examples/*.c) $(SRC_PATH)/doc/examples/Makefile $(SRC_PATH)/doc/examples/README
  
- SKIPHEADERS = cmdutils_common_opts.h
+ SKIPHEADERS = cmdutils_common_opts.h compat/w32pthreads.h
  
  include $(SRC_PATH)/common.mak
  
@@@ -4,20 -4,20 +4,20 @@@
   * Authors: Steven Walters <kemuri9@gmail.com>
   *          Pegasys Inc. <http://www.pegasys-inc.com>
   *
-- * This file is part of Libav.
++ * This file is part of FFmpeg.
   *
-- * Libav is free software; you can redistribute it and/or
++ * FFmpeg is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
-- * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
-- * License along with Libav; if not, write to the Free Software
++ * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -803,11 -679,10 +803,10 @@@ SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER
  SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
  SKIPHEADERS-$(CONFIG_VDA)              += vda.h
  SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h
- SKIPHEADERS-$(HAVE_W32THREADS)         += w32pthreads.h
 +SKIPHEADERS-$(HAVE_OS2THREADS)         += os2threads.h
  
 -EXAMPLES = api
 -
 -TESTPROGS = dct                                                         \
 +TESTPROGS = cabac                                                       \
 +            dct                                                         \
              fft                                                         \
              fft-fixed                                                   \
              golomb                                                      \
index b11a54a,0000000..98c50ab
mode 100644,000000..100644
--- /dev/null
@@@ -1,270 -1,0 +1,270 @@@
- #include "w32pthreads.h"
 +/*
 + * Copyright (c) 2012 Michael Niedermayer <michaelni@gmx.at>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "frame_thread_encoder.h"
 +
 +#include "libavutil/fifo.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/imgutils.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "thread.h"
 +
 +#if HAVE_PTHREADS
 +#include <pthread.h>
 +#elif HAVE_W32THREADS
++#include "compat/w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
 +#endif
 +
 +#define MAX_THREADS 64
 +#define BUFFER_SIZE (2*MAX_THREADS)
 +
 +typedef struct{
 +    void *indata;
 +    void *outdata;
 +    int64_t return_code;
 +    unsigned index;
 +} Task;
 +
 +typedef struct{
 +    AVCodecContext *parent_avctx;
 +    pthread_mutex_t buffer_mutex;
 +
 +    AVFifoBuffer *task_fifo;
 +    pthread_mutex_t task_fifo_mutex;
 +    pthread_cond_t task_fifo_cond;
 +
 +    Task finished_tasks[BUFFER_SIZE];
 +    pthread_mutex_t finished_task_mutex;
 +    pthread_cond_t finished_task_cond;
 +
 +    unsigned task_index;
 +    unsigned finished_task_index;
 +
 +    pthread_t worker[MAX_THREADS];
 +    int exit;
 +} ThreadContext;
 +
 +static void * attribute_align_arg worker(void *v){
 +    AVCodecContext *avctx = v;
 +    ThreadContext *c = avctx->internal->frame_thread_encoder;
 +    AVPacket *pkt = NULL;
 +
 +    while(!c->exit){
 +        int got_packet, ret;
 +        AVFrame *frame;
 +        Task task;
 +
 +        if(!pkt) pkt= av_mallocz(sizeof(*pkt));
 +        if(!pkt) continue;
 +        av_init_packet(pkt);
 +
 +        pthread_mutex_lock(&c->task_fifo_mutex);
 +        while (av_fifo_size(c->task_fifo) <= 0 || c->exit) {
 +            if(c->exit){
 +                pthread_mutex_unlock(&c->task_fifo_mutex);
 +                goto end;
 +            }
 +            pthread_cond_wait(&c->task_fifo_cond, &c->task_fifo_mutex);
 +        }
 +        av_fifo_generic_read(c->task_fifo, &task, sizeof(task), NULL);
 +        pthread_mutex_unlock(&c->task_fifo_mutex);
 +        frame = task.indata;
 +
 +        ret = avcodec_encode_video2(avctx, pkt, frame, &got_packet);
 +        pthread_mutex_lock(&c->buffer_mutex);
 +        av_frame_unref(frame);
 +        pthread_mutex_unlock(&c->buffer_mutex);
 +        av_frame_free(&frame);
 +        if(got_packet) {
 +            av_dup_packet(pkt);
 +        } else {
 +            pkt->data = NULL;
 +            pkt->size = 0;
 +        }
 +        pthread_mutex_lock(&c->finished_task_mutex);
 +        c->finished_tasks[task.index].outdata = pkt; pkt = NULL;
 +        c->finished_tasks[task.index].return_code = ret;
 +        pthread_cond_signal(&c->finished_task_cond);
 +        pthread_mutex_unlock(&c->finished_task_mutex);
 +    }
 +end:
 +    av_free(pkt);
 +    pthread_mutex_lock(&c->buffer_mutex);
 +    avcodec_close(avctx);
 +    pthread_mutex_unlock(&c->buffer_mutex);
 +    av_freep(&avctx);
 +    return NULL;
 +}
 +
 +int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
 +    int i=0;
 +    ThreadContext *c;
 +
 +
 +    if(   !(avctx->thread_type & FF_THREAD_FRAME)
 +       || !(avctx->codec->capabilities & CODEC_CAP_INTRA_ONLY))
 +        return 0;
 +
 +    if(!avctx->thread_count) {
 +        avctx->thread_count = ff_get_logical_cpus(avctx);
 +        avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
 +    }
 +
 +    if(avctx->thread_count <= 1)
 +        return 0;
 +
 +    if(avctx->thread_count > MAX_THREADS)
 +        return AVERROR(EINVAL);
 +
 +    av_assert0(!avctx->internal->frame_thread_encoder);
 +    c = avctx->internal->frame_thread_encoder = av_mallocz(sizeof(ThreadContext));
 +    if(!c)
 +        return AVERROR(ENOMEM);
 +
 +    c->parent_avctx = avctx;
 +
 +    c->task_fifo = av_fifo_alloc(sizeof(Task) * BUFFER_SIZE);
 +    if(!c->task_fifo)
 +        goto fail;
 +
 +    pthread_mutex_init(&c->task_fifo_mutex, NULL);
 +    pthread_mutex_init(&c->finished_task_mutex, NULL);
 +    pthread_mutex_init(&c->buffer_mutex, NULL);
 +    pthread_cond_init(&c->task_fifo_cond, NULL);
 +    pthread_cond_init(&c->finished_task_cond, NULL);
 +
 +    for(i=0; i<avctx->thread_count ; i++){
 +        AVDictionary *tmp = NULL;
 +        void *tmpv;
 +        AVCodecContext *thread_avctx = avcodec_alloc_context3(avctx->codec);
 +        if(!thread_avctx)
 +            goto fail;
 +        tmpv = thread_avctx->priv_data;
 +        *thread_avctx = *avctx;
 +        thread_avctx->priv_data = tmpv;
 +        thread_avctx->internal = NULL;
 +        memcpy(thread_avctx->priv_data, avctx->priv_data, avctx->codec->priv_data_size);
 +        thread_avctx->thread_count = 1;
 +        thread_avctx->active_thread_type &= ~FF_THREAD_FRAME;
 +
 +        av_dict_copy(&tmp, options, 0);
 +        av_dict_set(&tmp, "threads", "1", 0);
 +        if(avcodec_open2(thread_avctx, avctx->codec, &tmp) < 0) {
 +            av_dict_free(&tmp);
 +            goto fail;
 +        }
 +        av_dict_free(&tmp);
 +        av_assert0(!thread_avctx->internal->frame_thread_encoder);
 +        thread_avctx->internal->frame_thread_encoder = c;
 +        if(pthread_create(&c->worker[i], NULL, worker, thread_avctx)) {
 +            goto fail;
 +        }
 +    }
 +
 +    avctx->active_thread_type = FF_THREAD_FRAME;
 +
 +    return 0;
 +fail:
 +    avctx->thread_count = i;
 +    av_log(avctx, AV_LOG_ERROR, "ff_frame_thread_encoder_init failed\n");
 +    ff_frame_thread_encoder_free(avctx);
 +    return -1;
 +}
 +
 +void ff_frame_thread_encoder_free(AVCodecContext *avctx){
 +    int i;
 +    ThreadContext *c= avctx->internal->frame_thread_encoder;
 +
 +    pthread_mutex_lock(&c->task_fifo_mutex);
 +    c->exit = 1;
 +    pthread_cond_broadcast(&c->task_fifo_cond);
 +    pthread_mutex_unlock(&c->task_fifo_mutex);
 +
 +    for (i=0; i<avctx->thread_count; i++) {
 +         pthread_join(c->worker[i], NULL);
 +    }
 +
 +    pthread_mutex_destroy(&c->task_fifo_mutex);
 +    pthread_mutex_destroy(&c->finished_task_mutex);
 +    pthread_mutex_destroy(&c->buffer_mutex);
 +    pthread_cond_destroy(&c->task_fifo_cond);
 +    pthread_cond_destroy(&c->finished_task_cond);
 +    av_fifo_free(c->task_fifo); c->task_fifo = NULL;
 +    av_freep(&avctx->internal->frame_thread_encoder);
 +}
 +
 +int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr){
 +    ThreadContext *c = avctx->internal->frame_thread_encoder;
 +    Task task;
 +    int ret;
 +
 +    av_assert1(!*got_packet_ptr);
 +
 +    if(frame){
 +        if(!(avctx->flags & CODEC_FLAG_INPUT_PRESERVED)){
 +            AVFrame *new = av_frame_alloc();
 +            if(!new)
 +                return AVERROR(ENOMEM);
 +            pthread_mutex_lock(&c->buffer_mutex);
 +            ret = ff_get_buffer(c->parent_avctx, new, 0);
 +            pthread_mutex_unlock(&c->buffer_mutex);
 +            if(ret<0)
 +                return ret;
 +            new->pts = frame->pts;
 +            new->quality = frame->quality;
 +            new->pict_type = frame->pict_type;
 +            av_image_copy(new->data, new->linesize, (const uint8_t **)frame->data, frame->linesize,
 +                          avctx->pix_fmt, avctx->width, avctx->height);
 +            frame = new;
 +        }
 +
 +        task.index = c->task_index;
 +        task.indata = (void*)frame;
 +        pthread_mutex_lock(&c->task_fifo_mutex);
 +        av_fifo_generic_write(c->task_fifo, &task, sizeof(task), NULL);
 +        pthread_cond_signal(&c->task_fifo_cond);
 +        pthread_mutex_unlock(&c->task_fifo_mutex);
 +
 +        c->task_index = (c->task_index+1) % BUFFER_SIZE;
 +
 +        if(!c->finished_tasks[c->finished_task_index].outdata && (c->task_index - c->finished_task_index) % BUFFER_SIZE <= avctx->thread_count)
 +            return 0;
 +    }
 +
 +    if(c->task_index == c->finished_task_index)
 +        return 0;
 +
 +    pthread_mutex_lock(&c->finished_task_mutex);
 +    while (!c->finished_tasks[c->finished_task_index].outdata) {
 +        pthread_cond_wait(&c->finished_task_cond, &c->finished_task_mutex);
 +    }
 +    task = c->finished_tasks[c->finished_task_index];
 +    *pkt = *(AVPacket*)(task.outdata);
 +    if(pkt->data)
 +        *got_packet_ptr = 1;
 +    av_freep(&c->finished_tasks[c->finished_task_index].outdata);
 +    c->finished_task_index = (c->finished_task_index+1) % BUFFER_SIZE;
 +    pthread_mutex_unlock(&c->finished_task_mutex);
 +
 +    return task.return_code;
 +}
@@@ -61,9 -58,7 +61,9 @@@
  #if HAVE_PTHREADS
  #include <pthread.h>
  #elif HAVE_W32THREADS
- #include "w32pthreads.h"
+ #include "compat/w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
  #endif
  
  typedef int (action_func)(AVCodecContext *c, void *arg);
@@@ -36,9 -36,7 +36,9 @@@
  #if HAVE_PTHREADS
  #include <pthread.h>
  #elif HAVE_W32THREADS
- #include "w32pthreads.h"
+ #include "compat/w32pthreads.h"
 +#elif HAVE_OS2THREADS
 +#include "os2threads.h"
  #endif
  
  #define VP8_MAX_QUANT 127
  #if HAVE_THREADS
  #if HAVE_PTHREADS
  #include <pthread.h>
 +#elif HAVE_OS2THREADS
 +#include "libavcodec/os2threads.h"
  #else
- #include "libavcodec/w32pthreads.h"
+ #include "compat/w32pthreads.h"
  #endif
  #endif