/// Releases the buffers that this decoding thread was the last user of. static void release_delayed_buffers(PerThreadContext *p) { FrameThreadContext *fctx = p->parent; while (p->num_released_buffers > 0) { AVFrame *f; pthread_mutex_lock(&fctx->buffer_mutex); // fix extended data in case the caller screwed it up av_assert0(p->avctx->codec_type == AVMEDIA_TYPE_VIDEO || p->avctx->codec_type == AVMEDIA_TYPE_AUDIO); f = &p->released_buffers[--p->num_released_buffers]; f->extended_data = f->data; av_frame_unref(f); pthread_mutex_unlock(&fctx->buffer_mutex); } }
void CDVDVideoCodecFFmpeg::Reset() { m_started = false; m_interlaced = false; m_decoderPts = DVD_NOPTS_VALUE; m_skippedDeint = 0; m_droppedFrames = 0; m_eof = false; m_iLastKeyframe = m_pCodecContext->has_b_frames; avcodec_flush_buffers(m_pCodecContext); av_frame_unref(m_pFrame); if (m_pHardware) m_pHardware->Reset(); m_filters = ""; FilterClose(); m_dropCtrl.Reset(false); }
bool MovieDecoder::decodeVideoPacket() { if (m_pPacket->stream_index != m_VideoStream) { return false; } av_frame_unref(m_pFrame); int frameFinished; int bytesDecoded = avcodec_decode_video2(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket); if (bytesDecoded < 0) { throw logic_error("Failed to decode video frame: bytesDecoded < 0"); } return frameFinished > 0; }
AudioPlayerLoader::ReadResult FFMpegLoader::readMore(QByteArray &result, int64 &samplesAdded) { int res; av_frame_unref(frame); res = avcodec_receive_frame(codecContext, frame); if (res >= 0) { return readFromReadyFrame(result, samplesAdded); } if (res == AVERROR_EOF) { return ReadResult::EndOfFile; } else if (res != AVERROR(EAGAIN)) { char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; LOG(("Audio Error: Unable to avcodec_receive_frame() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return ReadResult::Error; } if ((res = av_read_frame(fmtContext, &avpkt)) < 0) { if (res != AVERROR_EOF) { char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; LOG(("Audio Error: Unable to av_read_frame() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); return ReadResult::Error; } avcodec_send_packet(codecContext, nullptr); // drain return ReadResult::Ok; } if (avpkt.stream_index == streamId) { res = avcodec_send_packet(codecContext, &avpkt); if (res < 0) { av_packet_unref(&avpkt); char err[AV_ERROR_MAX_STRING_SIZE] = { 0 }; LOG(("Audio Error: Unable to avcodec_send_packet() file '%1', data size '%2', error %3, %4").arg(file.name()).arg(data.size()).arg(res).arg(av_make_error_string(err, sizeof(err), res))); if (res == AVERROR_INVALIDDATA) { return ReadResult::NotYet; // try to skip bad packet } return ReadResult::Error; } } av_packet_unref(&avpkt); return ReadResult::Ok; }
int VideoDecoder::decodeVideoPacket() { int frameFinished; if (mPacketPtr->stream_index != mVideoIndex) { return -1; } if (mFramePtr) { av_frame_unref(mFramePtr); } int bytesDecoded = avcodec_decode_video2(mVideoCodecCtxPtr, mFramePtr, &frameFinished, mPacketPtr); if (bytesDecoded < 0) { LOGE("Decode failed"); return -1; } return frameFinished == 0 ? 0 : 1; }
static int audio_get_buffer(AVCodecContext *avctx, AVFrame *frame) { FramePool *pool = avctx->internal->pool; int planes = pool->planes; int i; frame->linesize[0] = pool->linesize[0]; if (planes > AV_NUM_DATA_POINTERS) { frame->extended_data = av_mallocz(planes * sizeof(*frame->extended_data)); frame->nb_extended_buf = planes - AV_NUM_DATA_POINTERS; frame->extended_buf = av_mallocz(frame->nb_extended_buf * sizeof(*frame->extended_buf)); if (!frame->extended_data || !frame->extended_buf) { av_freep(&frame->extended_data); av_freep(&frame->extended_buf); return AVERROR(ENOMEM); } } else frame->extended_data = frame->data; for (i = 0; i < FFMIN(planes, AV_NUM_DATA_POINTERS); i++) { frame->buf[i] = av_buffer_pool_get(pool->pools[0]); if (!frame->buf[i]) goto fail; frame->extended_data[i] = frame->data[i] = frame->buf[i]->data; } for (i = 0; i < frame->nb_extended_buf; i++) { frame->extended_buf[i] = av_buffer_pool_get(pool->pools[0]); if (!frame->extended_buf[i]) goto fail; frame->extended_data[i + AV_NUM_DATA_POINTERS] = frame->extended_buf[i]->data; } if (avctx->debug & FF_DEBUG_BUFFERS) av_log(avctx, AV_LOG_DEBUG, "default_get_buffer called on frame %p", frame); return 0; fail: av_frame_unref(frame); return AVERROR(ENOMEM); }
static void libav_video_flush(media_codec_t *mc, video_decoder_t *vd) { int got_pic = 0; AVCodecContext *ctx = mc->ctx; AVFrame *frame = vd->vd_frame; AVPacket avpkt; av_init_packet(&avpkt); avpkt.data = NULL; avpkt.size = 0; while(1) { avcodec_decode_video2(ctx, vd->vd_frame, &got_pic, &avpkt); if(!got_pic) break; av_frame_unref(frame); }; avcodec_flush_buffers(ctx); }
void CVideoBufferDRMPRIME::Unref() { if (m_fb_id) { drmModeRmFB(m_drm_fd, m_fb_id); m_fb_id = 0; } for (int i = 0; i < AV_DRM_MAX_PLANES; i++) { if (m_handles[i]) { struct drm_gem_close gem_close = { .handle = m_handles[i] }; drmIoctl(m_drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close); m_handles[i] = 0; } } av_frame_unref(m_pFrame); }
/** * 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; const AVCodec *codec = avctx->codec; pthread_mutex_lock(&p->mutex); while (1) { while (p->state == STATE_INPUT_READY && !fctx->die) pthread_cond_wait(&p->input_cond, &p->mutex); if (fctx->die) break; if (!codec->update_thread_context && THREAD_SAFE_CALLBACKS(avctx)) ff_thread_finish_setup(avctx); av_frame_unref(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); pthread_mutex_lock(&p->progress_mutex); #if 0 //BUFREF-FIXME for (i = 0; i < MAX_BUFFERS; i++) if (p->progress_used[i] && (p->got_frame || p->result<0 || avctx->codec_id != AV_CODEC_ID_H264)) { p->progress[i][0] = INT_MAX; p->progress[i][1] = INT_MAX; } #endif p->state = STATE_INPUT_READY; 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; }
int cellAdecGetPcm(u32 handle, vm::ptr<float> outBuffer) { cellAdec->Log("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer.addr()); AudioDecoder* adec; if (!Emu.GetIdManager().GetIDData(handle, adec)) { return CELL_ADEC_ERROR_ARG; } if (adec->frames.IsEmpty()) { return CELL_ADEC_ERROR_EMPTY; } AdecFrame af; adec->frames.Pop(af); AVFrame* frame = af.data; if (!af.data) // fake: empty data { return CELL_OK; } // reverse byte order, extract data: float* in_f[2]; in_f[0] = (float*)frame->extended_data[0]; in_f[1] = (float*)frame->extended_data[1]; for (u32 i = 0; i < af.size / 8; i++) { outBuffer[i * 2 + 0] = in_f[0][i]; outBuffer[i * 2 + 1] = in_f[1][i]; } if (af.data) { av_frame_unref(af.data); av_frame_free(&af.data); } return CELL_OK; }
static av_cold void uninit(AVFilterContext *ctx) { BufferSinkContext *sink = ctx->priv; AVFrame *frame; if (sink->audio_fifo) av_audio_fifo_free(sink->audio_fifo); if (sink->fifo) { while (av_fifo_size(sink->fifo) >= sizeof(AVFilterBufferRef *)) { av_fifo_generic_read(sink->fifo, &frame, sizeof(frame), NULL); av_frame_unref(frame); } av_fifo_free(sink->fifo); sink->fifo = NULL; } av_freep(&sink->pixel_fmts); av_freep(&sink->sample_fmts); av_freep(&sink->sample_rates); av_freep(&sink->channel_layouts); }
static int qtrle_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *pict, int *got_packet) { QtrleEncContext * const s = avctx->priv_data; int ret; if ((ret = ff_alloc_packet2(avctx, pkt, s->max_buf_size, 0)) < 0) return ret; if (avctx->gop_size == 0 || (s->avctx->frame_number % avctx->gop_size) == 0) { /* I-Frame */ s->key_frame = 1; } else { /* P-Frame */ s->key_frame = 0; } pkt->size = encode_frame(s, pict, pkt->data); /* save the current frame */ av_frame_unref(s->previous_frame); ret = av_frame_ref(s->previous_frame, pict); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "cannot add reference\n"); return ret; } #if FF_API_CODED_FRAME FF_DISABLE_DEPRECATION_WARNINGS avctx->coded_frame->key_frame = s->key_frame; avctx->coded_frame->pict_type = s->key_frame ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; FF_ENABLE_DEPRECATION_WARNINGS #endif if (s->key_frame) pkt->flags |= AV_PKT_FLAG_KEY; *got_packet = 1; return 0; }
int FrameQueue::get(AVFrame *frame , bool block) { AVFrameList *frame1; int ret; pthread_mutex_lock(&mutex); for(;;) { frame1 = first_frame; if (frame1) { first_frame = frame1->next; if (!first_frame){ last_frame = NULL; } node_count --; av_frame_ref(frame, frame1->frame); // set frame av_frame_unref(frame1->frame); av_frame_free(&frame1->frame); av_free(frame1); ret = 1; break; } else if (!block) { // notify_buffering_start(); ret = 0; break; }else { // notify_buffering_start(); pthread_cond_wait(&cond, &mutex); } } pthread_mutex_unlock(&mutex); return ret; }
AVFrame* FFmpegDataDecoder<LIBAV_VER>::PrepareFrame() { #if LIBAVCODEC_VERSION_MAJOR >= 55 if (mFrame) { av_frame_unref(mFrame); } else { mFrame = av_frame_alloc(); } #elif LIBAVCODEC_VERSION_MAJOR == 54 if (mFrame) { avcodec_get_frame_defaults(mFrame); } else { mFrame = avcodec_alloc_frame(); } #else delete mFrame; mFrame = new AVFrame; avcodec_get_frame_defaults(mFrame); #endif return mFrame; }
static void libav_decode_video(struct media_codec *mc, struct video_decoder *vd, struct media_queue *mq, struct media_buf *mb, int reqsize) { int got_pic = 0; media_pipe_t *mp = vd->vd_mp; AVCodecContext *ctx = mc->ctx; AVFrame *frame = vd->vd_frame; int t; if(mb->mb_flush) libav_video_eof(mc, vd, mq); copy_mbm_from_mb(&vd->vd_reorder[vd->vd_reorder_ptr], mb); ctx->reordered_opaque = vd->vd_reorder_ptr; vd->vd_reorder_ptr = (vd->vd_reorder_ptr + 1) & VIDEO_DECODER_REORDER_MASK; /* * If we are seeking, drop any non-reference frames */ ctx->skip_frame = mb->mb_skip == 1 ? AVDISCARD_NONREF : AVDISCARD_DEFAULT; avgtime_start(&vd->vd_decode_time); avcodec_decode_video2(ctx, frame, &got_pic, &mb->mb_pkt); t = avgtime_stop(&vd->vd_decode_time, mq->mq_prop_decode_avg, mq->mq_prop_decode_peak); if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); if(got_pic == 0) return; const media_buf_meta_t *mbm = &vd->vd_reorder[frame->reordered_opaque]; if(!mbm->mbm_skip) libav_deliver_frame(vd, mp, mq, ctx, frame, mbm, t, mc); av_frame_unref(frame); }
bool MovieDecoder::decodeVideoPacket() { if (m_pPacket->stream_index != m_VideoStream) { return false; } av_frame_unref(m_pFrame); int frameFinished = 0; #if LIBAVCODEC_VERSION_MAJOR < 53 int bytesDecoded = avcodec_decode_video(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket->data, m_pPacket->size); #else int bytesDecoded = avcodec_decode_video2(m_pVideoCodecContext, m_pFrame, &frameFinished, m_pPacket); #endif if (bytesDecoded < 0) { qDebug() << "Failed to decode video frame: bytesDecoded < 0"; } return (frameFinished > 0); }
void ff_decoder_free(struct ff_decoder *decoder) { void *decoder_thread_result; int i; assert(decoder != NULL); decoder->abort = true; ff_circular_queue_abort(&decoder->frame_queue); packet_queue_abort(&decoder->packet_queue); ff_timer_free(&decoder->refresh_timer); pthread_join(decoder->decoder_thread, &decoder_thread_result); for (i = 0; i < decoder->frame_queue.capacity; i++) { void *item = decoder->frame_queue.slots[i]; struct ff_frame *frame = (struct ff_frame *)item; ff_callbacks_frame_free(frame, decoder->callbacks); if (frame != NULL) { if (frame->frame != NULL) av_frame_unref(frame->frame); if (frame->clock != NULL) ff_clock_release(&frame->clock); av_free(frame); } } packet_queue_free(&decoder->packet_queue); ff_circular_queue_free(&decoder->frame_queue); avcodec_close(decoder->codec); av_free(decoder); }
AVFrame* FFmpegDataDecoder<LIBAV_VER>::PrepareFrame() { MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); #if LIBAVCODEC_VERSION_MAJOR >= 55 if (mFrame) { av_frame_unref(mFrame); } else { mFrame = av_frame_alloc(); } #elif LIBAVCODEC_VERSION_MAJOR == 54 if (mFrame) { avcodec_get_frame_defaults(mFrame); } else { mFrame = avcodec_alloc_frame(); } #else delete mFrame; mFrame = new AVFrame; avcodec_get_frame_defaults(mFrame); #endif return mFrame; }
static int video_get_buffer(AVCodecContext *s, AVFrame *pic) { FramePool *pool = s->internal->pool; int i; if (pic->data[0]) { av_log(s, AV_LOG_ERROR, "pic->data[0]!=NULL in avcodec_default_get_buffer\n"); return -1; } memset(pic->data, 0, sizeof(pic->data)); pic->extended_data = pic->data; for (i = 0; i < 4 && pool->pools[i]; i++) { pic->linesize[i] = pool->linesize[i]; pic->buf[i] = av_buffer_pool_get(pool->pools[i]); if (!pic->buf[i]) goto fail; pic->data[i] = pic->buf[i]->data; } for (; i < AV_NUM_DATA_POINTERS; i++) { pic->data[i] = NULL; pic->linesize[i] = 0; } if (pic->data[1] && !pic->data[2]) avpriv_set_systematic_pal2((uint32_t *)pic->data[1], s->pix_fmt); if (s->debug & FF_DEBUG_BUFFERS) av_log(s, AV_LOG_DEBUG, "default_get_buffer called on pic %p\n", pic); return 0; fail: av_frame_unref(pic); return AVERROR(ENOMEM); }
VideoDecoder::~VideoDecoder() { // TODO: check finalization VdecFrame vf; while (frames.try_pop(vf)) { av_frame_unref(vf.data); av_frame_free(&vf.data); } if (ctx) { avcodec_close(ctx); avformat_close_input(&fmt); } if (fmt) { if (io_buf) { av_free(io_buf); } if (fmt->pb) av_free(fmt->pb); avformat_free_context(fmt); } }
static int codec_reinit(AVCodecContext *avctx, int width, int height, int quality) { NuvContext *c = avctx->priv_data; int ret; width = FFALIGN(width, 2); height = FFALIGN(height, 2); if (quality >= 0) get_quant_quality(c, quality); if (width != c->width || height != c->height) { // also reserve space for a possible additional header int buf_size = height * width * 3 / 2 + FFMAX(AV_LZO_OUTPUT_PADDING, FF_INPUT_BUFFER_PADDING_SIZE) + RTJPEG_HEADER_SIZE; if (buf_size > INT_MAX/8) return -1; if ((ret = av_image_check_size(height, width, 0, avctx)) < 0) return ret; avctx->width = c->width = width; avctx->height = c->height = height; av_fast_malloc(&c->decomp_buf, &c->decomp_size, buf_size); if (!c->decomp_buf) { av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); return AVERROR(ENOMEM); } ff_rtjpeg_decode_init(&c->rtj, c->width, c->height, c->lq, c->cq); av_frame_unref(c->pic); return 1; } else if (quality != c->quality) ff_rtjpeg_decode_init(&c->rtj, c->width, c->height, c->lq, c->cq); return 0; }
VideoDecoder::~VideoDecoder() { // TODO: check finalization if (ctx) { for (u32 i = frames.GetCount() - 1; ~i; i--) { VdecFrame& vf = frames.Peek(i); av_frame_unref(vf.data); av_frame_free(&vf.data); } avcodec_close(ctx); avformat_close_input(&fmt); } if (fmt) { if (io_buf) { av_free(io_buf); } if (fmt->pb) av_free(fmt->pb); avformat_free_context(fmt); } }
int CDVDVideoCodecFFmpeg::FilterProcess(AVFrame* frame) { int result; if (frame || (m_codecControlFlags & DVD_CODEC_CTRL_DRAIN)) { result = av_buffersrc_add_frame(m_pFilterIn, frame); if (result < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersrc_add_frame"); return VC_ERROR; } } result = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame); if (result == AVERROR(EAGAIN)) return VC_BUFFER; else if (result == AVERROR_EOF) { result = av_buffersink_get_frame(m_pFilterOut, m_pFilterFrame); m_filterEof = true; if (result < 0) return VC_BUFFER; } else if (result < 0) { CLog::Log(LOGERROR, "CDVDVideoCodecFFmpeg::FilterProcess - av_buffersink_get_frame"); return VC_ERROR; } av_frame_unref(m_pFrame); av_frame_move_ref(m_pFrame, m_pFilterFrame); return VC_PICTURE; }
virtual void onData(LiveTrack* track, uint8_t* p_buffer, int i_size, int i_truncated_bytes, int64_t pts, int64_t dts) { //std::cout << "Got Data. size = " << i_size << "; truncated bytes = " << i_truncated_bytes << "; pts = " << pts << "; dts = " << dts << std::endl; //std::cout << "Got Data. size = " << i_size << "; pts = " << pts << std::endl; int consumed; if (track->getFormat().i_codec != VLC_CODEC_H264) return; //std::cout << "Got H264 Data. size = " << i_size << "; truncated bytes = " << i_truncated_bytes << "; NAL type = " << (int)(p_buffer[4] & 0x1f) << std::endl; if (!decoder) { decoder = new VideoDecoder(); decoder->openCodec(0); if (track->getFormat().p_extra) { decoder->decode(track->getFormat().p_extra, track->getFormat().i_extra, consumed); } } uint8_t* tmp = p_buffer; int left = i_size; while (left) { AVFrame* ret = decoder->decode(tmp, left, consumed); if (ret) { av_frame_unref(ret); #ifdef TEST_MULTI_CLIENT std::cout << "client " << this << " got frame!!!\n"; #endif } tmp += consumed; left -= consumed; } }
EXPORT int start_capture(void *actx) { struct liveStream *ctx = (struct liveStream *)actx; int got_frame; int ret; AVPacket packet; AVFormatContext *ic; long long start_time; struct lsInput* input = NULL; AVRational av_time_base_q = {1, AV_TIME_BASE}; if(!ctx) { ret = -1; goto end; } while(1) { AVCodecContext *dec_ctx = NULL; input = get_best_input(ctx); if(!input) { continue; } dec_ctx = input->dec_ctx; ic = input->ic; if (ic->start_time != AV_NOPTS_VALUE) start_time = ic->start_time; ret = get_input_packet(input,&packet); if (ret == AVERROR(EAGAIN)) { continue; } else if (ret == AVERROR_EOF) { output_packet(input,NULL); input->eof_reached = 1; continue; } if(ret < 0) { av_log(NULL,AV_LOG_ERROR,"No Input packet %x\n",ret); break; } if(input->id != 1) { if (packet.pts != AV_NOPTS_VALUE) { packet.pts -= av_rescale_q(start_time, av_time_base_q, ic->streams[0]->time_base); } if (packet.dts != AV_NOPTS_VALUE) packet.dts -= av_rescale_q(start_time, av_time_base_q, ic->streams[0]->time_base); } if(packet.stream_index == 0) { ret = avcodec_decode_video2(dec_ctx, input->InFrame, &got_frame, &packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding video\n"); goto end; } if(!got_frame) continue; } else { continue; } av_free_packet(&packet); input->InFrame->pts = av_frame_get_best_effort_timestamp(input->InFrame); take_filter_lock(&ctx->filter_lock); if (av_buffersrc_add_frame_flags(input->in_filter, input->InFrame, AV_BUFFERSRC_FLAG_PUSH) < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); } give_filter_lock(&ctx->filter_lock); reap_filter(ctx); } av_frame_unref(input->InFrame); end: return ret; }
s32 cellVdecGetPicture(u32 handle, vm::cptr<CellVdecPicFormat> format, vm::ptr<u8> outBuff) { cellVdec.Log("cellVdecGetPicture(handle=0x%x, format=*0x%x, outBuff=*0x%x)", handle, format, outBuff); const auto vdec = Emu.GetIdManager().get<VideoDecoder>(handle); if (!vdec || !format) { return CELL_VDEC_ERROR_ARG; } VdecFrame vf; if (!vdec->frames.try_pop(vf)) { //std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack return CELL_VDEC_ERROR_EMPTY; } if (!vf.data) { // hack return CELL_OK; } std::unique_ptr<AVFrame, void(*)(AVFrame*)> frame(vf.data, [](AVFrame* frame) { av_frame_unref(frame); av_frame_free(&frame); }); if (outBuff) { const auto f = vdec->ctx->pix_fmt; const auto w = vdec->ctx->width; const auto h = vdec->ctx->height; auto out_f = AV_PIX_FMT_YUV420P; std::unique_ptr<u8[]> alpha_plane; switch (const u32 type = format->formatType) { case CELL_VDEC_PICFMT_ARGB32_ILV: out_f = AV_PIX_FMT_ARGB; alpha_plane.reset(new u8[w * h]); break; case CELL_VDEC_PICFMT_RGBA32_ILV: out_f = AV_PIX_FMT_RGBA; alpha_plane.reset(new u8[w * h]); break; case CELL_VDEC_PICFMT_UYVY422_ILV: out_f = AV_PIX_FMT_UYVY422; break; case CELL_VDEC_PICFMT_YUV420_PLANAR: out_f = AV_PIX_FMT_YUV420P; break; default: { throw EXCEPTION("Unknown formatType(%d)", type); } } if (format->colorMatrixType != CELL_VDEC_COLOR_MATRIX_TYPE_BT709) { throw EXCEPTION("Unknown colorMatrixType(%d)", format->colorMatrixType); } if (alpha_plane) { memset(alpha_plane.get(), format->alpha, w * h); } auto in_f = AV_PIX_FMT_YUV420P; switch (f) { case AV_PIX_FMT_YUV420P: in_f = alpha_plane ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; break; default: { throw EXCEPTION("Unknown pix_fmt(%d)", f); } } std::unique_ptr<SwsContext, void(*)(SwsContext*)> sws(sws_getContext(w, h, in_f, w, h, out_f, SWS_POINT, NULL, NULL, NULL), sws_freeContext); u8* in_data[4] = { frame->data[0], frame->data[1], frame->data[2], alpha_plane.get() }; int in_line[4] = { frame->linesize[0], frame->linesize[1], frame->linesize[2], w * 1 }; u8* out_data[4] = { outBuff.get_ptr() }; int out_line[4] = { w * 4 }; if (!alpha_plane) { out_data[1] = out_data[0] + w * h; out_data[2] = out_data[0] + w * h * 5 / 4; out_line[0] = w; out_line[1] = w / 2; out_line[2] = w / 2; } sws_scale(sws.get(), in_data, in_line, 0, h, out_data, out_line); //const u32 buf_size = align(av_image_get_buffer_size(vdec->ctx->pix_fmt, vdec->ctx->width, vdec->ctx->height, 1), 128); //// TODO: zero padding bytes //int err = av_image_copy_to_buffer(outBuff.get_ptr(), buf_size, frame->data, frame->linesize, vdec->ctx->pix_fmt, frame->width, frame->height, 1); //if (err < 0) //{ // cellVdec.Fatal("cellVdecGetPicture: av_image_copy_to_buffer failed (err=0x%x)", err); //} } return CELL_OK; }
int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) { cellAdec.Log("cellAdecGetPcm(handle=%d, outBuffer_addr=0x%x)", handle, outBuffer_addr); AudioDecoder* adec; if (!Emu.GetIdManager().GetIDData(handle, adec)) { return CELL_ADEC_ERROR_ARG; } if (adec->frames.IsEmpty()) { return CELL_ADEC_ERROR_EMPTY; } AdecFrame af; adec->frames.Pop(af); AVFrame* frame = af.data; int result = CELL_OK; if (!Memory.IsGoodAddr(outBuffer_addr, af.size)) { result = CELL_ADEC_ERROR_FATAL; goto end; } if (!af.data) // fake: empty data { /*u8* buf = (u8*)malloc(4096); memset(buf, 0, 4096); Memory.CopyFromReal(outBuffer_addr, buf, 4096); free(buf);*/ goto end; } // copy data SwrContext* swr = nullptr; u8* out = nullptr; out = (u8*)malloc(af.size); /*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000, frame->channel_layout, (AVSampleFormat)frame->format, frame->sample_rate, 0, NULL); if (!swr) { ConLog.Error("cellAdecGetPcm(%d): swr_alloc_set_opts() failed", handle); Emu.Pause(); goto end; } // something is wrong swr_convert(swr, &out, frame->nb_samples, (const u8**)frame->extended_data, frame->nb_samples); */ // reverse byte order, extract data: float* in_f[2]; in_f[0] = (float*)frame->extended_data[0]; in_f[1] = (float*)frame->extended_data[1]; be_t<float>* out_f = (be_t<float>*)out; for (u32 i = 0; i < af.size / 8; i++) { out_f[i*2] = in_f[0][i]; out_f[i*2+1] = in_f[1][i]; } if (!Memory.CopyFromReal(outBuffer_addr, out, af.size)) { ConLog.Error("cellAdecGetPcm(%d): data copying failed (addr=0x%x)", handle, outBuffer_addr); Emu.Pause(); } end: if (out) free(out); if (swr) swr_free(&swr); if (af.data) { av_frame_unref(af.data); av_frame_free(&af.data); } return result; }
int main(int argc, char **argv) { int ret; AVPacket packet; AVFrame *frame = av_frame_alloc(); AVFrame *filt_frame = av_frame_alloc(); int got_frame; if (!frame || !filt_frame) { perror("Could not allocate frame"); exit(1); } if (argc != 2) { fprintf(stderr, "Usage: %s file\n", argv[0]); exit(1); } avcodec_register_all(); av_register_all(); avfilter_register_all(); if ((ret = open_input_file(argv[1])) < 0) goto end; if ((ret = init_filters(filter_descr)) < 0) goto end; /* read all packets */ while (1) { if ((ret = av_read_frame(fmt_ctx, &packet)) < 0) break; if (packet.stream_index == video_stream_index) { avcodec_get_frame_defaults(frame); got_frame = 0; ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, &packet); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Error decoding video\n"); break; } if (got_frame) { frame->pts = av_frame_get_best_effort_timestamp(frame); /* push the decoded frame into the filtergraph */ if (av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF) < 0) { av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); break; } /* pull filtered frames from the filtergraph */ while (1) { ret = av_buffersink_get_frame(buffersink_ctx, filt_frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) break; if (ret < 0) goto end; display_frame(filt_frame, buffersink_ctx->inputs[0]->time_base); av_frame_unref(filt_frame); } av_frame_unref(frame); } } av_free_packet(&packet); } end: avfilter_graph_free(&filter_graph); if (dec_ctx) avcodec_close(dec_ctx); avformat_close_input(&fmt_ctx); av_frame_free(&frame); av_frame_free(&filt_frame); if (ret < 0 && ret != AVERROR_EOF) { char buf[1024]; av_strerror(ret, buf, sizeof(buf)); fprintf(stderr, "Error occurred: %s\n", buf); exit(1); } exit(0); }
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; NuvContext *c = avctx->priv_data; AVFrame *picture = data; int orig_size = buf_size; int keyframe, ret; int size_change = 0; int result, init_frame = !avctx->frame_number; enum { NUV_UNCOMPRESSED = '0', NUV_RTJPEG = '1', NUV_RTJPEG_IN_LZO = '2', NUV_LZO = '3', NUV_BLACK = 'N', NUV_COPY_LAST = 'L' } comptype; if (buf_size < 12) { av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); return AVERROR_INVALIDDATA; } // codec data (rtjpeg quant tables) if (buf[0] == 'D' && buf[1] == 'R') { int ret; // skip rest of the frameheader. buf = &buf[12]; buf_size -= 12; ret = get_quant(avctx, c, buf, buf_size); if (ret < 0) return ret; ff_rtjpeg_decode_init(&c->rtj, c->width, c->height, c->lq, c->cq); return orig_size; } if (buf_size < 12 || buf[0] != 'V') { av_log(avctx, AV_LOG_ERROR, "not a nuv video frame\n"); return AVERROR_INVALIDDATA; } comptype = buf[1]; switch (comptype) { case NUV_RTJPEG_IN_LZO: case NUV_RTJPEG: keyframe = !buf[2]; break; case NUV_COPY_LAST: keyframe = 0; break; default: keyframe = 1; break; } retry: // skip rest of the frameheader. buf = &buf[12]; buf_size -= 12; if (comptype == NUV_RTJPEG_IN_LZO || comptype == NUV_LZO) { int outlen = c->decomp_size - FFMAX(FF_INPUT_BUFFER_PADDING_SIZE, AV_LZO_OUTPUT_PADDING); int inlen = buf_size; if (av_lzo1x_decode(c->decomp_buf, &outlen, buf, &inlen)) { av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); return AVERROR_INVALIDDATA; } buf = c->decomp_buf; buf_size = c->decomp_size - FFMAX(FF_INPUT_BUFFER_PADDING_SIZE, AV_LZO_OUTPUT_PADDING) - outlen; memset(c->decomp_buf + buf_size, 0, FF_INPUT_BUFFER_PADDING_SIZE); } if (c->codec_frameheader) { int w, h, q; if (buf_size < RTJPEG_HEADER_SIZE) { av_log(avctx, AV_LOG_ERROR, "Too small NUV video frame\n"); return AVERROR_INVALIDDATA; } // There seem to exist two variants of this header: one starts with 'V' // and 5 bytes unknown, the other matches current MythTV and is 4 bytes size, // 1 byte header size (== 12), 1 byte version (== 0) if (buf[0] != 'V' && AV_RL16(&buf[4]) != 0x000c) { av_log(avctx, AV_LOG_ERROR, "Unknown secondary frame header (wrong codec_tag?)\n"); return AVERROR_INVALIDDATA; } w = AV_RL16(&buf[6]); h = AV_RL16(&buf[8]); q = buf[10]; if ((result = codec_reinit(avctx, w, h, q)) < 0) return result; if (result) { buf = avpkt->data; buf_size = avpkt->size; size_change = 1; goto retry; } buf = &buf[RTJPEG_HEADER_SIZE]; buf_size -= RTJPEG_HEADER_SIZE; } if (size_change || keyframe) { av_frame_unref(c->pic); init_frame = 1; } if ((result = ff_reget_buffer(avctx, c->pic)) < 0) return result; if (init_frame) { memset(c->pic->data[0], 0, avctx->height * c->pic->linesize[0]); memset(c->pic->data[1], 0x80, avctx->height * c->pic->linesize[1] / 2); memset(c->pic->data[2], 0x80, avctx->height * c->pic->linesize[2] / 2); } c->pic->pict_type = keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; c->pic->key_frame = keyframe; // decompress/copy/whatever data switch (comptype) { case NUV_LZO: case NUV_UNCOMPRESSED: { int height = c->height; if (buf_size < c->width * height * 3 / 2) { av_log(avctx, AV_LOG_ERROR, "uncompressed frame too short\n"); height = buf_size / c->width / 3 * 2; } if(height > 0) copy_frame(c->pic, buf, c->width, height); break; } case NUV_RTJPEG_IN_LZO: case NUV_RTJPEG: ret = ff_rtjpeg_decode_frame_yuv420(&c->rtj, c->pic, buf, buf_size); if (ret < 0) return ret; break; case NUV_BLACK: memset(c->pic->data[0], 0, c->width * c->height); memset(c->pic->data[1], 128, c->width * c->height / 4); memset(c->pic->data[2], 128, c->width * c->height / 4); break; case NUV_COPY_LAST: /* nothing more to do here */ break; default: av_log(avctx, AV_LOG_ERROR, "unknown compression\n"); return AVERROR_INVALIDDATA; } if ((result = av_frame_ref(picture, c->pic)) < 0) return result; *got_frame = 1; return orig_size; }
static int get_requested_picture ( libavsmash_video_decode_handler_t *vdhp, AVFrame *picture, uint32_t sample_number ) { #define MAX_ERROR_COUNT 3 /* arbitrary */ codec_configuration_t *config = &vdhp->config; uint32_t config_index; if( sample_number < vdhp->first_valid_frame_number || vdhp->sample_count == 1 ) { /* Get the index of the decoder configuration. */ lsmash_sample_t sample; uint32_t decoding_sample_number = get_decoding_sample_number( vdhp->order_converter, vdhp->first_valid_frame_number ); if( lsmash_get_sample_info_from_media_timeline( vdhp->root, vdhp->track_id, decoding_sample_number, &sample ) < 0 ) goto video_fail; config_index = sample.index; /* Copy the first valid video frame data. */ av_frame_unref( picture ); if( av_frame_ref( picture, vdhp->first_valid_frame ) < 0 ) goto video_fail; /* Force seeking at the next access for valid video frame. */ vdhp->last_sample_number = vdhp->sample_count + 1; goto return_frame; } uint32_t start_number; /* number of sample, for normal decoding, where decoding starts excluding decoding delay */ uint32_t rap_number; /* number of sample, for seeking, where decoding starts excluding decoding delay */ int seek_mode = vdhp->seek_mode; int roll_recovery = 0; if( sample_number > vdhp->last_sample_number && sample_number <= vdhp->last_sample_number + vdhp->forward_seek_threshold ) { start_number = vdhp->last_sample_number + 1 + config->delay_count; rap_number = vdhp->last_rap_number; } else { roll_recovery = find_random_accessible_point( vdhp, sample_number, 0, &rap_number ); if( rap_number == vdhp->last_rap_number && sample_number > vdhp->last_sample_number ) { roll_recovery = 0; start_number = vdhp->last_sample_number + 1 + config->delay_count; } else { /* Require starting to decode from random accessible sample. */ vdhp->last_rap_number = rap_number; start_number = seek_video( vdhp, picture, sample_number, rap_number, roll_recovery || seek_mode != SEEK_MODE_NORMAL ); } } /* Get the desired picture. */ int error_count = 0; while( start_number == 0 /* Failed to seek. */ || config->update_pending /* Need to update the decoder configuration to decode pictures. */ || get_picture( vdhp, picture, start_number, sample_number + config->delay_count ) < 0 ) { if( config->update_pending ) { roll_recovery = find_random_accessible_point( vdhp, sample_number, 0, &rap_number ); vdhp->last_rap_number = rap_number; } else { /* Failed to get the desired picture. */ if( config->error || seek_mode == SEEK_MODE_AGGRESSIVE ) goto video_fail; if( ++error_count > MAX_ERROR_COUNT || rap_number <= 1 ) { if( seek_mode == SEEK_MODE_UNSAFE ) goto video_fail; /* Retry to decode from the same random accessible sample with error ignorance. */ seek_mode = SEEK_MODE_AGGRESSIVE; } else { /* Retry to decode from more past random accessible sample. */ roll_recovery = find_random_accessible_point( vdhp, sample_number, rap_number - 1, &rap_number ); if( vdhp->last_rap_number == rap_number ) goto video_fail; vdhp->last_rap_number = rap_number; } } start_number = seek_video( vdhp, picture, sample_number, rap_number, roll_recovery || seek_mode != SEEK_MODE_NORMAL ); } vdhp->last_sample_number = sample_number; config_index = config->index; return_frame:; /* Don't exceed the maximum presentation size specified for each sequence. */ extended_summary_t *extended = &config->entries[ config_index - 1 ].extended; if( config->ctx->width > extended->width ) config->ctx->width = extended->width; if( config->ctx->height > extended->height ) config->ctx->height = extended->height; return 0; video_fail: /* fatal error of decoding */ lw_log_show( &config->lh, LW_LOG_WARNING, "Couldn't read video frame." ); return -1; #undef MAX_ERROR_COUNT }