int AndCodec_EasyDecoderFlush(int dec) { and_log_writeline_simple(0, LOG_DEBUG, "AndCodec_EasyDecoderFlush()"); if(!dec) { and_log_writeline_simple(0, LOG_ERROR, "decoder handle is null"); return -1; } easy_decoder_handle* handle = (easy_decoder_handle *)dec; return decode_flush(handle); }
static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { AVFrame *frame = data; const uint8_t *buf = avpkt->data; const uint8_t *buf_end = buf + avpkt->size; KgvContext * const c = avctx->priv_data; int offsets[8]; uint8_t *out, *prev; int outcnt = 0, maxcnt; int w, h, i, res; if (avpkt->size < 2) return AVERROR_INVALIDDATA; w = (buf[0] + 1) * 8; h = (buf[1] + 1) * 8; buf += 2; if (w != avctx->width || h != avctx->height) { av_freep(&c->frame_buffer); av_freep(&c->last_frame_buffer); if ((res = ff_set_dimensions(avctx, w, h)) < 0) return res; } if (!c->frame_buffer) { c->frame_buffer = av_mallocz(avctx->width * avctx->height * 2); c->last_frame_buffer = av_mallocz(avctx->width * avctx->height * 2); if (!c->frame_buffer || !c->last_frame_buffer) { decode_flush(avctx); return AVERROR(ENOMEM); } } maxcnt = w * h; if ((res = ff_get_buffer(avctx, frame, 0)) < 0) return res; out = (uint8_t*)c->frame_buffer; prev = (uint8_t*)c->last_frame_buffer; for (i = 0; i < 8; i++) offsets[i] = -1; while (outcnt < maxcnt && buf_end - 2 >= buf) { int code = AV_RL16(buf); buf += 2; if (!(code & 0x8000)) { AV_WN16A(&out[2 * outcnt], code); // rgb555 pixel coded directly outcnt++; } else { int count; if ((code & 0x6000) == 0x6000) { // copy from previous frame int oidx = (code >> 10) & 7; int start; count = (code & 0x3FF) + 3; if (offsets[oidx] < 0) { if (buf_end - 3 < buf) break; offsets[oidx] = AV_RL24(buf); buf += 3; } start = (outcnt + offsets[oidx]) % maxcnt; if (maxcnt - start < count || maxcnt - outcnt < count) break; if (!prev) { av_log(avctx, AV_LOG_ERROR, "Frame reference does not exist\n"); break; } memcpy(out + 2 * outcnt, prev + 2 * start, 2 * count); } else { // copy from earlier in this frame int offset = (code & 0x1FFF) + 1; if (!(code & 0x6000)) { count = 2; } else if ((code & 0x6000) == 0x2000) { count = 3; } else { if (buf_end - 1 < buf) break; count = 4 + *buf++; } if (outcnt < offset || maxcnt - outcnt < count) break; av_memcpy_backptr(out + 2 * outcnt, 2 * offset, 2 * count); } outcnt += count; }
static int decode_data(easy_decoder_handle* handle, unsigned char* pData, int datalen, unsigned char* pOpaque, int opaque_len) { pthread_mutex_lock(&handle->mutex); AVPacket pkt; int got_frame = 0; int ret; int written; int len; if(opaque_len != OPAQUE_DATA_LEN) { and_log_writeline_easy(0, LOG_ERROR, "opaque data size is wrong %d.%d", opaque_len, OPAQUE_DATA_LEN); got_frame = -1; goto exit; } av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; pkt.data = pData; pkt.size = datalen; and_log_writeline_easy(0, LOG_DEBUG, "decode frame size:[%d] %d", handle->dec_frames_num, datalen); while (pkt.size > 0) { ret = avcodec_decode_video2(handle->dec_ctx, handle->dec_frame, &got_frame, &pkt); if (ret < 0) { and_log_writeline_easy(0, LOG_WARN, "failed to decode #%d %d, ret %d", handle->dec_frames_num, datalen, ret); break; } handle->dec_frames_num++; if (got_frame) { and_log_writeline_easy(0, LOG_DEBUG, "got pic. type %d", handle->dec_frame->pict_type); handle->dec_pic_num++; filesize_t timestamp; if (handle->dec_frame->opaque) { and_sysutil_memcpy(×tamp, handle->dec_frame->opaque, sizeof(filesize_t)); and_log_writeline_easy(0, LOG_INFO, "frame opaque %lld", timestamp); } if(handle->pic_trans) { //to out_pix_fmt rgb565le and_log_writeline_easy(0, LOG_DEBUG, "scale begin. linesize_in:%d linesize_out:%d h:%d", handle->dec_frame->linesize[0], handle->out_frame->linesize[0], handle->dec_ctx->height); sws_scale(handle->img_convert_ctx, (uint8_t const**)handle->dec_frame->data, handle->dec_frame->linesize, 0, handle->dec_ctx->height, handle->out_frame->data, handle->out_frame->linesize); len = handle->out_frame->linesize[0]* handle->height; and_log_writeline_simple(0, LOG_DEBUG, "scale end."); } else //420p only { handle->out_frame = handle->dec_frame; len = handle->out_frame->linesize[0]* handle->height * 3 / 2 ; } and_log_writeline_easy(0, LOG_DEBUG, "line size:%d; pic len:%d.", handle->out_frame->linesize[0], len); written = and_fifo_write(&handle->fifo, (void *)&len, DECODER_FRAMESIZE_LEN); if (written != DECODER_FRAMESIZE_LEN) { and_log_writeline_easy(0, LOG_ERROR, "failed to write data size %d - %d", len, written); got_frame = -1; goto exit; } written = 0; if(handle->pic_trans) // rgb565le { written = and_fifo_write(&handle->fifo, (void *)handle->out_frame->data[0], len); } else //420p only { written += and_fifo_write(&handle->fifo, (void *)handle->out_frame->data[0], handle->out_frame->linesize[0] * handle->height); written += and_fifo_write(&handle->fifo, (void *)handle->out_frame->data[1], handle->out_frame->linesize[1] * handle->height/2); written += and_fifo_write(&handle->fifo, (void *)handle->out_frame->data[2], handle->out_frame->linesize[2] * handle->height/2); } if (written != len) { and_log_writeline_easy(0, LOG_ERROR, "failed to write %d - %d", len, written); got_frame = -1; goto exit; } if ( and_queue_put(&handle->queue, (void *)pOpaque) < 0) { got_frame = -1; goto exit; } //all done! break; } if(pkt.data) { pkt.data += ret; pkt.size -= ret; } } av_free_packet(&pkt); pkt.data = NULL; pkt.size = 0; if(!got_frame) { and_log_writeline_easy(0, LOG_WARN, "no picture decoded out in #%d", handle->dec_frames_num); if ( and_queue_put(&handle->queue, (void *)pOpaque) < 0) { got_frame = -1; goto exit; } } // handle->dec_frame->key_frame if (got_frame /*&& handle->dec_frames_num > 1*/ && AV_PICTURE_TYPE_I == handle->dec_frame->pict_type ) { while (decode_flush(handle) > 0) { and_log_writeline_easy(0, LOG_INFO, "flush picture out in #%d", handle->dec_frames_num); } int opaque_num = and_queue_used(&handle->queue); int cache_pic_num = and_fifo_used(&handle->fifo) / handle->out_framesize; int pop_num = opaque_num - cache_pic_num; if (pop_num > 0) { and_log_writeline_easy(0, LOG_INFO, "opaque list %d, cache picture %d, to drop %d", opaque_num, cache_pic_num, pop_num); OpaqueData op; while (pop_num > 0) { and_queue_get(&handle->queue, (void *)&op); and_log_writeline_easy(0, LOG_INFO, "discard opaque data"); pop_num--; } } } exit: pthread_mutex_unlock(&handle->mutex); return got_frame; }