static int vdadec_decode(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { VDADecoderContext *ctx = avctx->priv_data; AVFrame *pic = data; int ret; set_context(avctx); ret = ff_h264_decoder.decode(avctx, data, got_frame, avpkt); restore_context(avctx); if (*got_frame) { AVBufferRef *buffer = pic->buf[0]; VDABufferContext *context = av_buffer_get_opaque(buffer); CVPixelBufferRef cv_buffer = (CVPixelBufferRef)pic->data[3]; CVPixelBufferRetain(cv_buffer); CVPixelBufferLockBaseAddress(cv_buffer, 0); context->cv_buffer = cv_buffer; pic->format = ctx->pix_fmt; if (CVPixelBufferIsPlanar(cv_buffer)) { int i, count = CVPixelBufferGetPlaneCount(cv_buffer); av_assert0(count < 4); for (i = 0; i < count; i++) { pic->data[i] = CVPixelBufferGetBaseAddressOfPlane(cv_buffer, i); pic->linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_buffer, i); } } else { pic->data[0] = CVPixelBufferGetBaseAddress(cv_buffer); pic->linesize[0] = CVPixelBufferGetBytesPerRow(cv_buffer); } } avctx->pix_fmt = ctx->pix_fmt; return ret; }
/** * Codec worker thread. * * Automatically calls ff_thread_finish_setup() if the codec does * not provide an update_thread_context method, or if the codec returns * before calling it. */ static attribute_align_arg void *frame_worker_thread(void *arg) { PerThreadContext *p = arg; FrameThreadContext *fctx = p->parent; AVCodecContext *avctx = p->avctx; AVCodec *codec = avctx->codec; while (1) { int i; if (p->state == STATE_INPUT_READY && !fctx->die) { pthread_mutex_lock(&p->mutex); while (p->state == STATE_INPUT_READY && !fctx->die) pthread_cond_wait(&p->input_cond, &p->mutex); pthread_mutex_unlock(&p->mutex); } if (fctx->die) break; if (!codec->update_thread_context && (avctx->thread_safe_callbacks || avctx->get_buffer == avcodec_default_get_buffer)) ff_thread_finish_setup(avctx); pthread_mutex_lock(&p->mutex); avcodec_get_frame_defaults(&p->frame); p->got_frame = 0; p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt); if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); p->state = STATE_INPUT_READY; pthread_mutex_lock(&p->progress_mutex); for (i = 0; i < MAX_BUFFERS; i++) if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != CODEC_ID_H264)) { p->progress[i][0] = INT_MAX; p->progress[i][1] = INT_MAX; } pthread_cond_broadcast(&p->progress_cond); pthread_cond_signal(&p->output_cond); pthread_mutex_unlock(&p->progress_mutex); pthread_mutex_unlock(&p->mutex); } return NULL; }
/** * Codec worker thread. * * Automatically calls ff_thread_finish_setup() if the codec does * not provide an update_thread_context method, or if the codec returns * before calling it. */ static attribute_align_arg void *frame_worker_thread(void *arg) { PerThreadContext *p = arg; FrameThreadContext *fctx = p->parent; AVCodecContext *avctx = p->avctx; AVCodec *codec = avctx->codec; while (1) { if (p->state == STATE_INPUT_READY && !fctx->die) { pthread_mutex_lock(&p->mutex); while (p->state == STATE_INPUT_READY && !fctx->die) pthread_cond_wait(&p->input_cond, &p->mutex); pthread_mutex_unlock(&p->mutex); } if (fctx->die) break; if (!codec->update_thread_context && avctx->thread_safe_callbacks) ff_thread_finish_setup(avctx); pthread_mutex_lock(&p->mutex); avcodec_get_frame_defaults(&p->frame); p->got_frame = 0; p->result = codec->decode(avctx, &p->frame, &p->got_frame, &p->avpkt); if (p->state == STATE_SETTING_UP) ff_thread_finish_setup(avctx); p->state = STATE_INPUT_READY; pthread_mutex_lock(&p->progress_mutex); pthread_cond_signal(&p->output_cond); pthread_mutex_unlock(&p->progress_mutex); pthread_mutex_unlock(&p->mutex); } return NULL; }