|
|
|
@ -28,6 +28,7 @@ |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
#include "libavutil/imgutils.h" |
|
|
|
|
#include "libavutil/intreadwrite.h" |
|
|
|
|
#include "avcodec.h" |
|
|
|
|
#include "libschroedinger.h" |
|
|
|
|
|
|
|
|
@ -39,6 +40,12 @@ |
|
|
|
|
#include <schroedinger/schrodebug.h> |
|
|
|
|
#include <schroedinger/schrovideoformat.h> |
|
|
|
|
|
|
|
|
|
/** SchroFrame and Pts relation */ |
|
|
|
|
typedef struct LibSchroFrameContext { |
|
|
|
|
SchroFrame *frame; |
|
|
|
|
int64_t pts; |
|
|
|
|
} LibSchroFrameContext; |
|
|
|
|
|
|
|
|
|
/** libschroedinger decoder private data */ |
|
|
|
|
typedef struct SchroDecoderParams { |
|
|
|
|
/** Schroedinger video format */ |
|
|
|
@ -60,7 +67,7 @@ typedef struct SchroDecoderParams { |
|
|
|
|
int eos_pulled; |
|
|
|
|
|
|
|
|
|
/** decoded picture */ |
|
|
|
|
AVPicture dec_pic; |
|
|
|
|
AVFrame dec_frame; |
|
|
|
|
} SchroDecoderParams; |
|
|
|
|
|
|
|
|
|
typedef struct SchroParseUnitContext { |
|
|
|
@ -171,8 +178,8 @@ static void libschroedinger_handle_first_access_unit(AVCodecContext *avccontext) |
|
|
|
|
p_schro_params->format = schro_decoder_get_video_format(decoder); |
|
|
|
|
|
|
|
|
|
/* Tell Libav about sequence details. */ |
|
|
|
|
if (av_image_check_size(p_schro_params->format->width, p_schro_params->format->height, |
|
|
|
|
0, avccontext) < 0) { |
|
|
|
|
if (av_image_check_size(p_schro_params->format->width, |
|
|
|
|
p_schro_params->format->height, 0, avccontext) < 0) { |
|
|
|
|
av_log(avccontext, AV_LOG_ERROR, "invalid dimensions (%dx%d)\n", |
|
|
|
|
p_schro_params->format->width, p_schro_params->format->height); |
|
|
|
|
avccontext->height = avccontext->width = 0; |
|
|
|
@ -192,12 +199,6 @@ static void libschroedinger_handle_first_access_unit(AVCodecContext *avccontext) |
|
|
|
|
|
|
|
|
|
avccontext->time_base.den = p_schro_params->format->frame_rate_numerator; |
|
|
|
|
avccontext->time_base.num = p_schro_params->format->frame_rate_denominator; |
|
|
|
|
|
|
|
|
|
if (!p_schro_params->dec_pic.data[0]) |
|
|
|
|
avpicture_alloc(&p_schro_params->dec_pic, |
|
|
|
|
avccontext->pix_fmt, |
|
|
|
|
avccontext->width, |
|
|
|
|
avccontext->height); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int libschroedinger_decode_frame(AVCodecContext *avccontext, |
|
|
|
@ -206,16 +207,18 @@ static int libschroedinger_decode_frame(AVCodecContext *avccontext, |
|
|
|
|
{ |
|
|
|
|
const uint8_t *buf = avpkt->data; |
|
|
|
|
int buf_size = avpkt->size; |
|
|
|
|
int64_t pts = avpkt->pts; |
|
|
|
|
SchroTag *tag; |
|
|
|
|
|
|
|
|
|
SchroDecoderParams *p_schro_params = avccontext->priv_data; |
|
|
|
|
SchroDecoder *decoder = p_schro_params->decoder; |
|
|
|
|
AVPicture *picture = data; |
|
|
|
|
SchroBuffer *enc_buf; |
|
|
|
|
SchroFrame* frame; |
|
|
|
|
int state; |
|
|
|
|
int go = 1; |
|
|
|
|
int outer = 1; |
|
|
|
|
SchroParseUnitContext parse_ctx; |
|
|
|
|
LibSchroFrameContext *framewithpts = NULL; |
|
|
|
|
|
|
|
|
|
*data_size = 0; |
|
|
|
|
|
|
|
|
@ -230,6 +233,13 @@ static int libschroedinger_decode_frame(AVCodecContext *avccontext, |
|
|
|
|
/* Loop through all the individual parse units in the input buffer */ |
|
|
|
|
do { |
|
|
|
|
if ((enc_buf = find_next_parse_unit(&parse_ctx))) { |
|
|
|
|
/* Set Schrotag with the pts to be recovered after decoding*/ |
|
|
|
|
enc_buf->tag = schro_tag_new(av_malloc(sizeof(int64_t)), av_free); |
|
|
|
|
if (!enc_buf->tag->value) { |
|
|
|
|
av_log(avccontext, AV_LOG_ERROR, "Unable to allocate SchroTag\n"); |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
AV_WN(64, enc_buf->tag->value, pts); |
|
|
|
|
/* Push buffer into decoder. */ |
|
|
|
|
if (SCHRO_PARSE_CODE_IS_PICTURE(enc_buf->data[4]) && |
|
|
|
|
SCHRO_PARSE_CODE_NUM_REFS(enc_buf->data[4]) > 0) |
|
|
|
@ -263,11 +273,21 @@ static int libschroedinger_decode_frame(AVCodecContext *avccontext, |
|
|
|
|
|
|
|
|
|
case SCHRO_DECODER_OK: |
|
|
|
|
/* Pull a frame out of the decoder. */ |
|
|
|
|
tag = schro_decoder_get_picture_tag(decoder); |
|
|
|
|
frame = schro_decoder_pull(decoder); |
|
|
|
|
|
|
|
|
|
if (frame) |
|
|
|
|
if (frame) { |
|
|
|
|
/* Add relation between schroframe and pts. */ |
|
|
|
|
framewithpts = av_malloc(sizeof(LibSchroFrameContext)); |
|
|
|
|
if (!framewithpts) { |
|
|
|
|
av_log(avccontext, AV_LOG_ERROR, "Unable to allocate FrameWithPts\n"); |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
framewithpts->frame = frame; |
|
|
|
|
framewithpts->pts = AV_RN64(tag->value); |
|
|
|
|
ff_schro_queue_push_back(&p_schro_params->dec_frame_queue, |
|
|
|
|
frame); |
|
|
|
|
framewithpts); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
case SCHRO_DECODER_EOS: |
|
|
|
|
go = 0; |
|
|
|
@ -284,30 +304,46 @@ static int libschroedinger_decode_frame(AVCodecContext *avccontext, |
|
|
|
|
} while (outer); |
|
|
|
|
|
|
|
|
|
/* Grab next frame to be returned from the top of the queue. */ |
|
|
|
|
frame = ff_schro_queue_pop(&p_schro_params->dec_frame_queue); |
|
|
|
|
framewithpts = ff_schro_queue_pop(&p_schro_params->dec_frame_queue); |
|
|
|
|
|
|
|
|
|
if (framewithpts && framewithpts->frame) { |
|
|
|
|
if (p_schro_params->dec_frame.data[0]) |
|
|
|
|
avccontext->release_buffer(avccontext, &p_schro_params->dec_frame); |
|
|
|
|
if (avccontext->get_buffer(avccontext, &p_schro_params->dec_frame) < 0) { |
|
|
|
|
av_log(avccontext, AV_LOG_ERROR, "Unable to allocate buffer\n"); |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (frame) { |
|
|
|
|
memcpy(p_schro_params->dec_pic.data[0], |
|
|
|
|
frame->components[0].data, |
|
|
|
|
frame->components[0].length); |
|
|
|
|
memcpy(p_schro_params->dec_frame.data[0], |
|
|
|
|
framewithpts->frame->components[0].data, |
|
|
|
|
framewithpts->frame->components[0].length); |
|
|
|
|
|
|
|
|
|
memcpy(p_schro_params->dec_pic.data[1], |
|
|
|
|
frame->components[1].data, |
|
|
|
|
frame->components[1].length); |
|
|
|
|
memcpy(p_schro_params->dec_frame.data[1], |
|
|
|
|
framewithpts->frame->components[1].data, |
|
|
|
|
framewithpts->frame->components[1].length); |
|
|
|
|
|
|
|
|
|
memcpy(p_schro_params->dec_pic.data[2], |
|
|
|
|
frame->components[2].data, |
|
|
|
|
frame->components[2].length); |
|
|
|
|
memcpy(p_schro_params->dec_frame.data[2], |
|
|
|
|
framewithpts->frame->components[2].data, |
|
|
|
|
framewithpts->frame->components[2].length); |
|
|
|
|
|
|
|
|
|
/* Fill picture with current buffer data from Schroedinger. */ |
|
|
|
|
avpicture_fill(picture, p_schro_params->dec_pic.data[0], |
|
|
|
|
avccontext->pix_fmt, |
|
|
|
|
avccontext->width, avccontext->height); |
|
|
|
|
/* Fill frame with current buffer data from Schroedinger. */ |
|
|
|
|
p_schro_params->dec_frame.format = -1; /* Unknown -1 */ |
|
|
|
|
p_schro_params->dec_frame.width = framewithpts->frame->width; |
|
|
|
|
p_schro_params->dec_frame.height = framewithpts->frame->height; |
|
|
|
|
p_schro_params->dec_frame.pkt_pts = framewithpts->pts; |
|
|
|
|
p_schro_params->dec_frame.linesize[0] = framewithpts->frame->components[0].stride; |
|
|
|
|
p_schro_params->dec_frame.linesize[1] = framewithpts->frame->components[1].stride; |
|
|
|
|
p_schro_params->dec_frame.linesize[2] = framewithpts->frame->components[2].stride; |
|
|
|
|
|
|
|
|
|
*data_size = sizeof(AVPicture); |
|
|
|
|
*(AVFrame*)data = p_schro_params->dec_frame; |
|
|
|
|
*data_size = sizeof(AVFrame); |
|
|
|
|
|
|
|
|
|
/* Now free the frame resources. */ |
|
|
|
|
libschroedinger_decode_frame_free(frame); |
|
|
|
|
libschroedinger_decode_frame_free(framewithpts->frame); |
|
|
|
|
av_free(framewithpts); |
|
|
|
|
} else { |
|
|
|
|
data = NULL; |
|
|
|
|
*data_size = 0; |
|
|
|
|
} |
|
|
|
|
return buf_size; |
|
|
|
|
} |
|
|
|
@ -320,7 +356,8 @@ static av_cold int libschroedinger_decode_close(AVCodecContext *avccontext) |
|
|
|
|
schro_decoder_free(p_schro_params->decoder); |
|
|
|
|
av_freep(&p_schro_params->format); |
|
|
|
|
|
|
|
|
|
avpicture_free(&p_schro_params->dec_pic); |
|
|
|
|
if (p_schro_params->dec_frame.data[0]) |
|
|
|
|
avccontext->release_buffer(avccontext, &p_schro_params->dec_frame); |
|
|
|
|
|
|
|
|
|
/* Free data in the output frame queue. */ |
|
|
|
|
ff_schro_queue_free(&p_schro_params->dec_frame_queue, |
|
|
|
|