Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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;
        }
Exemplo n.º 3
0
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(&timestamp, 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;
}