vp9: add mxext versions of the single-block (w=4,npx=8) h/v loopfilters.
[ffmpeg.git] / libavcodec / frame_thread_encoder.c
index 7865996..27ae356 100644 (file)
 #include "libavutil/fifo.h"
 #include "libavutil/avassert.h"
 #include "libavutil/imgutils.h"
+#include "libavutil/thread.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 "compat/os2threads.h"
-#endif
-
 #define MAX_THREADS 64
 #define BUFFER_SIZE (2*MAX_THREADS)
 
@@ -96,7 +89,9 @@ static void * attribute_align_arg worker(void *v){
         pthread_mutex_unlock(&c->buffer_mutex);
         av_frame_free(&frame);
         if(got_packet) {
-            av_dup_packet(pkt);
+            int ret2 = av_dup_packet(pkt);
+            if (ret >= 0 && ret2 < 0)
+                ret = ret2;
         } else {
             pkt->data = NULL;
             pkt->size = 0;
@@ -122,12 +117,12 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
 
 
     if(   !(avctx->thread_type & FF_THREAD_FRAME)
-       || !(avctx->codec->capabilities & CODEC_CAP_INTRA_ONLY))
+       || !(avctx->codec->capabilities & AV_CODEC_CAP_INTRA_ONLY))
         return 0;
 
     if(   !avctx->thread_count
        && avctx->codec_id == AV_CODEC_ID_MJPEG
-       && !(avctx->flags & CODEC_FLAG_QSCALE)) {
+       && !(avctx->flags & AV_CODEC_FLAG_QSCALE)) {
         av_log(avctx, AV_LOG_DEBUG,
                "Forcing thread count to 1 for MJPEG encoding, use -thread_type slice "
                "or a constant quantizer if you want to use multiple cpu cores\n");
@@ -135,10 +130,35 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
     }
     if(   avctx->thread_count > 1
        && avctx->codec_id == AV_CODEC_ID_MJPEG
-       && !(avctx->flags & CODEC_FLAG_QSCALE))
+       && !(avctx->flags & AV_CODEC_FLAG_QSCALE))
         av_log(avctx, AV_LOG_WARNING,
                "MJPEG CBR encoding works badly with frame multi-threading, consider "
                "using -threads 1, -thread_type slice or a constant quantizer.\n");
+
+    if (avctx->codec_id == AV_CODEC_ID_HUFFYUV ||
+        avctx->codec_id == AV_CODEC_ID_FFVHUFF) {
+        int warn = 0;
+        int context_model = 0;
+        AVDictionaryEntry *con = av_dict_get(options, "context", NULL, AV_DICT_MATCH_CASE);
+
+        if (con && con->value)
+            context_model = atoi(con->value);
+
+        if (avctx->flags & AV_CODEC_FLAG_PASS1)
+            warn = 1;
+        else if(context_model > 0) {
+            AVDictionaryEntry *t = av_dict_get(options, "non_deterministic",
+                                               NULL, AV_DICT_MATCH_CASE);
+            warn = !t || !t->value || !atoi(t->value) ? 1 : 0;
+        }
+        // huffyuv does not support these with multiple frame threads currently
+        if (warn) {
+            av_log(avctx, AV_LOG_WARNING,
+               "Forcing thread count to 1 for huffyuv encoding with first pass or context 1\n");
+            avctx->thread_count = 1;
+        }
+    }
+
     if(!avctx->thread_count) {
         avctx->thread_count = av_cpu_count();
         avctx->thread_count = FFMIN(avctx->thread_count, MAX_THREADS);
@@ -147,13 +167,6 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
     if(avctx->thread_count <= 1)
         return 0;
 
-    if (avctx->codec_id == AV_CODEC_ID_HUFFYUV ||
-        avctx->codec_id == AV_CODEC_ID_FFVHUFF) {
-        // huffyuv doesnt support these with multiple frame threads currently
-        if (avctx->context_model > 0 || (avctx->flags & CODEC_FLAG_PASS1))
-            return 0;
-    }
-
     if(avctx->thread_count > MAX_THREADS)
         return AVERROR(EINVAL);
 
@@ -164,7 +177,7 @@ int ff_frame_thread_encoder_init(AVCodecContext *avctx, AVDictionary *options){
 
     c->parent_avctx = avctx;
 
-    c->task_fifo = av_fifo_alloc(sizeof(Task) * BUFFER_SIZE);
+    c->task_fifo = av_fifo_alloc_array(BUFFER_SIZE, sizeof(Task));
     if(!c->task_fifo)
         goto fail;
 
@@ -230,7 +243,7 @@ void ff_frame_thread_encoder_free(AVCodecContext *avctx){
     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_fifo_freep(&c->task_fifo);
     av_freep(&avctx->internal->frame_thread_encoder);
 }
 
@@ -242,25 +255,17 @@ int ff_thread_video_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVF
     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;
+        AVFrame *new = av_frame_alloc();
+        if(!new)
+            return AVERROR(ENOMEM);
+        ret = av_frame_ref(new, frame);
+        if(ret < 0) {
+            av_frame_free(&new);
+            return ret;
         }
 
         task.index = c->task_index;
-        task.indata = (void*)frame;
+        task.indata = (void*)new;
         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);