/* Makes duplicates of data, side_data, but does not copy any other fields */ static int copy_packet_data(AVPacket *pkt, AVPacket *src, int dup) { pkt->data = NULL; pkt->side_data = NULL; if (pkt->buf) { AVBufferRef *ref = av_buffer_ref(src->buf); if (!ref) return AVERROR(ENOMEM); pkt->buf = ref; pkt->data = ref->data; } else { DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); } #if FF_API_DESTRUCT_PACKET pkt->destruct = dummy_destruct_packet; #endif if (pkt->side_data_elems && dup) pkt->side_data = src->side_data; if (pkt->side_data_elems && !dup) { return av_copy_packet_side_data(pkt, src); } return 0; failed_alloc: av_destruct_packet(pkt); return AVERROR(ENOMEM); }
FF_DISABLE_DEPRECATION_WARNINGS #define ALLOC_MALLOC(data, size) data = av_malloc(size) #define ALLOC_BUF(data, size) \ do { \ av_buffer_realloc(&pkt->buf, size); \ data = pkt->buf ? pkt->buf->data : NULL; \ } while (0) #define DUP_DATA(dst, src, size, padding, ALLOC) \ do { \ void *data; \ if (padding) { \ if ((unsigned)(size) > \ (unsigned)(size) + AV_INPUT_BUFFER_PADDING_SIZE) \ goto failed_alloc; \ ALLOC(data, size + AV_INPUT_BUFFER_PADDING_SIZE); \ } else { \ ALLOC(data, size); \ } \ if (!data) \ goto failed_alloc; \ memcpy(data, src, size); \ if (padding) \ memset((uint8_t *)data + size, 0, \ AV_INPUT_BUFFER_PADDING_SIZE); \ dst = data; \ } while (0) /* Makes duplicates of data, side_data, but does not copy any other fields */ static int copy_packet_data(AVPacket *pkt, const AVPacket *src, int dup) { pkt->data = NULL; pkt->side_data = NULL; pkt->side_data_elems = 0; if (pkt->buf) { AVBufferRef *ref = av_buffer_ref(src->buf); if (!ref) return AVERROR(ENOMEM); pkt->buf = ref; pkt->data = ref->data; } else { DUP_DATA(pkt->data, src->data, pkt->size, 1, ALLOC_BUF); } if (src->side_data_elems && dup) { pkt->side_data = src->side_data; pkt->side_data_elems = src->side_data_elems; } if (src->side_data_elems && !dup) { return av_copy_packet_side_data(pkt, src); } return 0; failed_alloc: av_packet_unref(pkt); return AVERROR(ENOMEM); }
static int submit_packet(PerThreadContext *p, AVPacket *avpkt) { FrameThreadContext *fctx = p->parent; PerThreadContext *prev_thread = fctx->prev_thread; const AVCodec *codec = p->avctx->codec; int ret; if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0; pthread_mutex_lock(&p->mutex); release_delayed_buffers(p); if (prev_thread) { int err; if (prev_thread->state == STATE_SETTING_UP) { pthread_mutex_lock(&prev_thread->progress_mutex); while (prev_thread->state == STATE_SETTING_UP) pthread_cond_wait(&prev_thread->progress_cond, &prev_thread->progress_mutex); pthread_mutex_unlock(&prev_thread->progress_mutex); } err = update_context_from_thread(p->avctx, prev_thread->avctx, 0); if (err) { pthread_mutex_unlock(&p->mutex); return err; } } av_packet_free_side_data(&p->avpkt); av_buffer_unref(&p->avpkt.buf); p->avpkt = *avpkt; if (avpkt->buf) p->avpkt.buf = av_buffer_ref(avpkt->buf); else { av_fast_malloc(&p->buf, &p->allocated_buf_size, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE); if (!p->buf) { pthread_mutex_unlock(&p->mutex); return AVERROR(ENOMEM); } p->avpkt.data = p->buf; memcpy(p->buf, avpkt->data, avpkt->size); memset(p->buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); } if ((ret = av_copy_packet_side_data(&p->avpkt, avpkt)) < 0) { pthread_mutex_unlock(&p->mutex); return ret; } p->state = STATE_SETTING_UP; pthread_cond_signal(&p->input_cond); pthread_mutex_unlock(&p->mutex); /* * If the client doesn't have a thread-safe get_buffer(), * then decoding threads call back to the main thread, * and it calls back to the client here. */ FF_DISABLE_DEPRECATION_WARNINGS if (!p->avctx->thread_safe_callbacks && ( p->avctx->get_format != avcodec_default_get_format || #if FF_API_GET_BUFFER p->avctx->get_buffer || #endif p->avctx->get_buffer2 != avcodec_default_get_buffer2)) { FF_ENABLE_DEPRECATION_WARNINGS while (p->state != STATE_SETUP_FINISHED && p->state != STATE_INPUT_READY) { int call_done = 1; pthread_mutex_lock(&p->progress_mutex); while (p->state == STATE_SETTING_UP) pthread_cond_wait(&p->progress_cond, &p->progress_mutex); switch (p->state) { case STATE_GET_BUFFER: p->result = ff_get_buffer(p->avctx, p->requested_frame, p->requested_flags); break; case STATE_GET_FORMAT: p->result_format = p->avctx->get_format(p->avctx, p->available_formats); break; default: call_done = 0; break; } if (call_done) { p->state = STATE_SETTING_UP; pthread_cond_signal(&p->progress_cond); } pthread_mutex_unlock(&p->progress_mutex); } }