* AVCodecInternal.hwaccel_priv_data.
*/
int priv_data_size;
+
+ /**
+ * Internal hwaccel capabilities.
+ */
+ int caps_internal;
} AVHWAccel;
/**
--- /dev/null
+/*
+ * This file is part of FFmpeg and was stolen from Libav.
+ *
+ * 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
+ */
+
+#ifndef AVCODEC_HWACCEL_H
+#define AVCODEC_HWACCEL_H
+
+#define HWACCEL_CAP_ASYNC_SAFE (1 << 0)
+
+#endif /* AVCODEC_HWACCEL_H */
#include <stdint.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "internal.h"
#include "pthread_internal.h"
#include "thread.h"
int die; ///< Set when the thread should exit.
int hwaccel_serializing;
+ int async_serializing;
} PerThreadContext;
/**
* is used.
*/
pthread_mutex_t hwaccel_mutex;
+ pthread_mutex_t async_mutex;
int next_decoding; ///< The next context to submit a packet to.
int next_finished; ///< The next context to return output from.
pthread_mutex_unlock(&p->parent->hwaccel_mutex);
}
+ if (p->async_serializing) {
+ p->async_serializing = 0;
+ pthread_mutex_unlock(&p->parent->async_mutex);
+ }
+
pthread_mutex_lock(&p->progress_mutex);
#if 0 //BUFREF-FIXME
for (i = 0; i < MAX_BUFFERS; i++)
FrameThreadContext *fctx = avctx->internal->thread_ctx;
int finished = fctx->next_finished;
PerThreadContext *p;
- int err;
+ int err, ret;
+
+ /* release the async lock, permitting blocked hwaccel threads to
+ * go forward while we are in this function */
+ pthread_mutex_unlock(&fctx->async_mutex);
/*
* Submit a packet to the next decoding thread.
p = &fctx->threads[fctx->next_decoding];
err = update_context_from_user(p->avctx, avctx);
- if (err) return err;
+ if (err)
+ goto finish;
err = submit_packet(p, avpkt);
- if (err) return err;
+ if (err)
+ goto finish;
/*
* If we're still receiving the initial packets, don't return a frame.
if (fctx->delaying) {
*got_picture_ptr=0;
- if (avpkt->size)
- return avpkt->size;
+ if (avpkt->size) {
+ ret = avpkt->size;
+ goto finish;
+ }
}
/*
* Otherwise the error can get lost.
*/
if (!avpkt->size && !*got_picture_ptr)
- return err;
+ goto finish;
/* return the size of the consumed packet if no error occurred */
- return (p->result >= 0) ? avpkt->size : p->result;
+ ret = (p->result >= 0) ? avpkt->size : p->result;
+finish:
+ pthread_mutex_lock(&fctx->async_mutex);
+ if (err < 0)
+ return err;
+ return ret;
}
void ff_thread_report_progress(ThreadFrame *f, int n, int field)
p->hwaccel_serializing = 1;
}
+ /* this assumes that no hwaccel calls happen before ff_thread_finish_setup() */
+ if (avctx->hwaccel &&
+ !(avctx->hwaccel->caps_internal & HWACCEL_CAP_ASYNC_SAFE)) {
+ p->async_serializing = 1;
+ pthread_mutex_lock(&p->parent->async_mutex);
+ }
+
pthread_mutex_lock(&p->progress_mutex);
if(atomic_load(&p->state) == STATE_SETUP_FINISHED){
av_log(avctx, AV_LOG_WARNING, "Multiple ff_thread_finish_setup() calls\n");
{
int i;
+ pthread_mutex_unlock(&fctx->async_mutex);
+
for (i = 0; i < thread_count; i++) {
PerThreadContext *p = &fctx->threads[i];
}
p->got_frame = 0;
}
+
+ pthread_mutex_lock(&fctx->async_mutex);
}
void ff_frame_thread_free(AVCodecContext *avctx, int thread_count)
av_freep(&fctx->threads);
pthread_mutex_destroy(&fctx->buffer_mutex);
pthread_mutex_destroy(&fctx->hwaccel_mutex);
+
+ pthread_mutex_unlock(&fctx->async_mutex);
+ pthread_mutex_destroy(&fctx->async_mutex);
+
av_freep(&avctx->internal->thread_ctx);
if (avctx->priv_data && avctx->codec && avctx->codec->priv_class)
pthread_mutex_init(&fctx->buffer_mutex, NULL);
pthread_mutex_init(&fctx->hwaccel_mutex, NULL);
+
+ pthread_mutex_init(&fctx->async_mutex, NULL);
+ pthread_mutex_lock(&fctx->async_mutex);
+
fctx->delaying = 1;
for (i = 0; i < thread_count; i++) {
#include "h264dec.h"
#include "h264_ps.h"
+#include "hwaccel.h"
#include "vaapi_decode.h"
/**
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "hwaccel.h"
#include "mpegutils.h"
#include "mpegvideo.h"
#include "internal.h"
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
*/
#include "h263.h"
+#include "hwaccel.h"
#include "internal.h"
#include "mpeg4video.h"
#include "mpegvideo.h"
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include "hwaccel.h"
#include "internal.h"
#include "vaapi_decode.h"
#include "vc1.h"
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
.init = &ff_vaapi_decode_init,
.uninit = &ff_vaapi_decode_uninit,
.priv_data_size = sizeof(VAAPIDecodeContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#include "internal.h"
#include "h264dec.h"
#include "h264_ps.h"
+#include "hwaccel.h"
#include "mpegutils.h"
#include "vdpau.h"
#include "vdpau_internal.h"
.init = vdpau_h264_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#include "avcodec.h"
#include "internal.h"
#include "hevc.h"
+#include "hwaccel.h"
#include "vdpau.h"
#include "vdpau_internal.h"
.init = vdpau_hevc_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#include <vdpau/vdpau.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "mpegvideo.h"
#include "vdpau.h"
#include "vdpau_internal.h"
.init = vdpau_mpeg1_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
.init = vdpau_mpeg2_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
#include <vdpau/vdpau.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "mpeg4video.h"
#include "vdpau.h"
#include "vdpau_internal.h"
.init = vdpau_mpeg4_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#include <vdpau/vdpau.h>
#include "avcodec.h"
+#include "hwaccel.h"
#include "vc1.h"
#include "vdpau.h"
#include "vdpau_internal.h"
.init = vdpau_vc1_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};
#endif
.init = vdpau_vc1_init,
.uninit = ff_vdpau_common_uninit,
.priv_data_size = sizeof(VDPAUContext),
+ .caps_internal = HWACCEL_CAP_ASYNC_SAFE,
};