static int ffmmal_add_packet(AVCodecContext *avctx, AVPacket *avpkt, int is_extradata) { MMALDecodeContext *ctx = avctx->priv_data; AVBufferRef *buf = NULL; int size = 0; uint8_t *data = (uint8_t *)""; uint8_t *start; int ret = 0; if (avpkt->size) { if (avpkt->buf) { buf = av_buffer_ref(avpkt->buf); size = avpkt->size; data = avpkt->data; } else { buf = av_buffer_alloc(avpkt->size); if (buf) { memcpy(buf->data, avpkt->data, avpkt->size); size = buf->size; data = buf->data; } } if (!buf) { ret = AVERROR(ENOMEM); goto done; } if (!is_extradata) ctx->packets_sent++; } else { if (!ctx->packets_sent) { // Short-cut the flush logic to avoid upsetting MMAL. ctx->eos_sent = 1; ctx->eos_received = 1; goto done; } } start = data; do { FFBufferEntry *buffer = av_mallocz(sizeof(*buffer)); if (!buffer) { ret = AVERROR(ENOMEM); goto done; } buffer->data = data; buffer->length = FFMIN(size, ctx->decoder->input[0]->buffer_size); if (is_extradata) buffer->flags |= MMAL_BUFFER_HEADER_FLAG_CONFIG; if (data == start) buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_START; data += buffer->length; size -= buffer->length; buffer->pts = avpkt->pts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->pts; buffer->dts = avpkt->dts == AV_NOPTS_VALUE ? MMAL_TIME_UNKNOWN : avpkt->dts; if (!size) buffer->flags |= MMAL_BUFFER_HEADER_FLAG_FRAME_END; if (!buffer->length) { buffer->flags |= MMAL_BUFFER_HEADER_FLAG_EOS; ctx->eos_sent = 1; } if (buf) { buffer->ref = av_buffer_ref(buf); if (!buffer->ref) { av_free(buffer); ret = AVERROR(ENOMEM); goto done; } } // Insert at end of the list if (!ctx->waiting_buffers) ctx->waiting_buffers = buffer; if (ctx->waiting_buffers_tail) ctx->waiting_buffers_tail->next = buffer; ctx->waiting_buffers_tail = buffer; } while (size); done: av_buffer_unref(&buf); return ret; }