static int libschroedinger_decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; int64_t pts = avpkt->pts; SchroTag *tag; SchroDecoderParams *p_schro_params = avctx->priv_data; SchroDecoder *decoder = p_schro_params->decoder; SchroBuffer *enc_buf; SchroFrame* frame; AVFrame *avframe = data; int state; int go = 1; int outer = 1; SchroParseUnitContext parse_ctx; LibSchroFrameContext *framewithpts = NULL; *got_frame = 0; parse_context_init(&parse_ctx, buf, buf_size); if (!buf_size) { if (!p_schro_params->eos_signalled) { state = schro_decoder_push_end_of_stream(decoder); p_schro_params->eos_signalled = 1; } } /* 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(avctx, 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) avctx->has_b_frames = 1; state = schro_decoder_push(decoder, enc_buf); if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) libschroedinger_handle_first_access_unit(avctx); go = 1; } else outer = 0; while (go) { /* Parse data and process result. */ state = schro_decoder_wait(decoder); switch (state) { case SCHRO_DECODER_FIRST_ACCESS_UNIT: libschroedinger_handle_first_access_unit(avctx); break; case SCHRO_DECODER_NEED_BITS: /* Need more input data - stop iterating over what we have. */ go = 0; break; case SCHRO_DECODER_NEED_FRAME: /* Decoder needs a frame - create one and push it in. */ frame = ff_create_schro_frame(avctx, p_schro_params->frame_format); if (!frame) return AVERROR(ENOMEM); schro_decoder_add_output_picture(decoder, frame); break; 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) { /* Add relation between schroframe and pts. */ framewithpts = av_malloc(sizeof(LibSchroFrameContext)); if (!framewithpts) { av_log(avctx, 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, framewithpts); } break; case SCHRO_DECODER_EOS: go = 0; p_schro_params->eos_pulled = 1; schro_decoder_reset(decoder); outer = 0; break; case SCHRO_DECODER_ERROR: return -1; break; } } } while (outer); /* Grab next frame to be returned from the top of the queue. */ framewithpts = ff_schro_queue_pop(&p_schro_params->dec_frame_queue); if (framewithpts && framewithpts->frame) { int ret; if ((ret = ff_get_buffer(avctx, avframe, 0)) < 0) return ret; memcpy(avframe->data[0], framewithpts->frame->components[0].data, framewithpts->frame->components[0].length); memcpy(avframe->data[1], framewithpts->frame->components[1].data, framewithpts->frame->components[1].length); memcpy(avframe->data[2], framewithpts->frame->components[2].data, framewithpts->frame->components[2].length); /* Fill frame with current buffer data from Schroedinger. */ avframe->pkt_pts = framewithpts->pts; avframe->linesize[0] = framewithpts->frame->components[0].stride; avframe->linesize[1] = framewithpts->frame->components[1].stride; avframe->linesize[2] = framewithpts->frame->components[2].stride; *got_frame = 1; /* Now free the frame resources. */ libschroedinger_decode_frame_free(framewithpts->frame); av_free(framewithpts); } else { data = NULL; *got_frame = 0; } return buf_size; }
void decode (FILE *file) { SchroDecoder *decoder; SchroBuffer *buffer; SchroVideoFormat *format = NULL; SchroFrame *frame; int picture_number; int go; int it; int eos = FALSE; void *packet; int size; int ret; int parse_code; decoder = schro_decoder_new(); schro_decoder_set_picture_order (decoder, SCHRO_DECODER_PICTURE_ORDER_CODED); while(!eos) { ret = parse_packet (file, &packet, &size); if (!ret) { exit(1); } if (size == 0) { schro_decoder_push_end_of_stream (decoder); } else { parse_code = ((uint8_t *)packet)[4]; buffer = schro_buffer_new_with_data (packet, size); buffer->free = buffer_free; buffer->priv = packet; printf("pushing 0x%02x size %d\n", parse_code, size); if (SCHRO_PARSE_CODE_IS_PICTURE (parse_code)) { frame = schro_frame_new_and_alloc (NULL, schro_params_get_frame_format(8, format->chroma_format), format->width, format->height); schro_decoder_add_output_picture (decoder, frame); } it = schro_decoder_push (decoder, buffer); if (it == SCHRO_DECODER_FIRST_ACCESS_UNIT) { format = schro_decoder_get_video_format (decoder); } if (!SCHRO_PARSE_CODE_IS_PICTURE (parse_code)) { continue; } } go = 1; while (go) { it = schro_decoder_wait (decoder); switch (it) { case SCHRO_DECODER_NEED_BITS: go = 0; break; case SCHRO_DECODER_NEED_FRAME: frame = schro_frame_new_and_alloc (NULL, schro_params_get_frame_format(8, format->chroma_format), format->width, format->height); schro_decoder_add_output_picture (decoder, frame); break; case SCHRO_DECODER_OK: picture_number = schro_decoder_get_picture_number (decoder); frame = schro_decoder_pull (decoder); printf("got frame %p, picture number %d\n", frame, picture_number); if (frame) { schro_frame_unref (frame); } go = 0; break; case SCHRO_DECODER_EOS: printf("got eos\n"); eos = TRUE; go = 0; break; case SCHRO_DECODER_STALLED: printf("stall\n"); go = 0; break; case SCHRO_DECODER_ERROR: exit(0); break; } } } printf("freeing decoder\n"); schro_decoder_free (decoder); free(format); }
static int libschroedinger_decode_frame(AVCodecContext *avccontext, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data; SchroDecoder *decoder = p_schro_params->decoder; SchroVideoFormat *format; AVPicture *picture = data; SchroBuffer *enc_buf; SchroFrame* frame; int state; int go = 1; int outer = 1; FfmpegSchroParseUnitContext parse_ctx; *data_size = 0; FfmpegSchroParseContextInit(&parse_ctx, buf, buf_size); if (!buf_size) { if (!p_schro_params->eos_signalled) { state = schro_decoder_push_end_of_stream(decoder); p_schro_params->eos_signalled = 1; } } /* Loop through all the individual parse units in the input buffer */ do { if ((enc_buf = FfmpegFindNextSchroParseUnit(&parse_ctx))) { /* Push buffer into decoder. */ if (SCHRO_PARSE_CODE_IS_PICTURE(enc_buf->data[4]) && SCHRO_PARSE_CODE_NUM_REFS(enc_buf->data[4]) > 0) avccontext->has_b_frames = 1; state = schro_decoder_push(decoder, enc_buf); if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) libschroedinger_handle_first_access_unit(avccontext); go = 1; } else outer = 0; format = p_schro_params->format; while (go) { /* Parse data and process result. */ state = schro_decoder_wait(decoder); switch (state) { case SCHRO_DECODER_FIRST_ACCESS_UNIT: libschroedinger_handle_first_access_unit(avccontext); break; case SCHRO_DECODER_NEED_BITS: /* Need more input data - stop iterating over what we have. */ go = 0; break; case SCHRO_DECODER_NEED_FRAME: /* Decoder needs a frame - create one and push it in. */ frame = ff_create_schro_frame(avccontext, p_schro_params->frame_format); schro_decoder_add_output_picture(decoder, frame); break; case SCHRO_DECODER_OK: /* Pull a frame out of the decoder. */ frame = schro_decoder_pull(decoder); if (frame) ff_dirac_schro_queue_push_back(&p_schro_params->dec_frame_queue, frame); break; case SCHRO_DECODER_EOS: go = 0; p_schro_params->eos_pulled = 1; schro_decoder_reset(decoder); outer = 0; break; case SCHRO_DECODER_ERROR: return -1; break; } } } while (outer); /* Grab next frame to be returned from the top of the queue. */ frame = ff_dirac_schro_queue_pop(&p_schro_params->dec_frame_queue); if (frame) { memcpy(p_schro_params->dec_pic.data[0], frame->components[0].data, 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_pic.data[2], frame->components[2].data, 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); *data_size = sizeof(AVPicture); /* Now free the frame resources. */ libschroedinger_decode_frame_free(frame); } return buf_size; }
static int libschroedinger_decode_frame(AVCodecContext *avccontext, void *data, int *data_size, const uint8_t *buf, int buf_size) { FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data; SchroDecoder *decoder = p_schro_params->decoder; SchroVideoFormat *format; AVPicture *picture = data; SchroBuffer *enc_buf; SchroFrame* frame; int state; int go = 1; *data_size = 0; if (buf_size>0) { unsigned char *in_buf = av_malloc(buf_size); memcpy (in_buf, buf, buf_size); enc_buf = schro_buffer_new_with_data (in_buf, buf_size); enc_buf->free = libschroedinger_decode_buffer_free; enc_buf->priv = in_buf; /* Push buffer into decoder. */ state = schro_decoder_push (decoder, enc_buf); if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) libschroedinger_handle_first_access_unit(avccontext); } else { if (!p_schro_params->eos_signalled) { state = schro_decoder_push_end_of_stream(decoder); p_schro_params->eos_signalled = 1; } } format = p_schro_params->format; while (go) { /* Parse data and process result. */ state = schro_decoder_wait (decoder); switch (state) { case SCHRO_DECODER_FIRST_ACCESS_UNIT: libschroedinger_handle_first_access_unit (avccontext); break; case SCHRO_DECODER_NEED_BITS: /* Need more input data - stop iterating over what we have. */ go = 0; break; case SCHRO_DECODER_NEED_FRAME: /* Decoder needs a frame - create one and push it in. */ frame = schro_frame_new_and_alloc(NULL, p_schro_params->frame_format, format->width, format->height); schro_decoder_add_output_picture (decoder, frame); break; case SCHRO_DECODER_OK: /* Pull a frame out of the decoder. */ frame = schro_decoder_pull (decoder); if (frame) { ff_dirac_schro_queue_push_back( &p_schro_params->dec_frame_queue, frame); } break; case SCHRO_DECODER_EOS: go = 0; p_schro_params->eos_pulled = 1; schro_decoder_reset (decoder); break; case SCHRO_DECODER_ERROR: return -1; break; } } /* Grab next frame to be returned from the top of the queue. */ frame = ff_dirac_schro_queue_pop(&p_schro_params->dec_frame_queue); if (frame != NULL) { memcpy (p_schro_params->dec_pic.data[0], frame->components[0].data, 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_pic.data[2], frame->components[2].data, 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); *data_size = sizeof(AVPicture); /* Now free the frame resources. */ libschroedinger_decode_frame_free (frame); } return buf_size; }
static gavl_source_status_t decode_picture(bgav_stream_t * s) { int state; SchroBuffer * buf = NULL; SchroFrame * frame = NULL; schroedinger_priv_t* priv; gavl_source_status_t st; priv = s->decoder_priv; while(1) { state = schro_decoder_wait(priv->dec); switch (state) { case SCHRO_DECODER_FIRST_ACCESS_UNIT: // fprintf(stderr, "State: SCHRO_DECODER_FIRST_ACCESS_UNIT\n"); get_format(s); // libschroedinger_handle_first_access_unit (avccontext); break; case SCHRO_DECODER_NEED_BITS: /* Need more input data - stop iterating over what we have. */ // fprintf(stderr, "State: SCHRO_DECODER_NEED_BITS\n"); st = get_data(s, &buf); #if 1 if(st == GAVL_SOURCE_OK) { state = schro_decoder_push(priv->dec, buf); if(state == SCHRO_DECODER_FIRST_ACCESS_UNIT) { // fprintf(stderr, "State: SCHRO_DECODER_FIRST_ACCESS_UNIT\n"); get_format(s); } } #endif break; case SCHRO_DECODER_NEED_FRAME: /* Decoder needs a frame - create one and push it in. */ // fprintf(stderr, "State: SCHRO_DECODER_NEED_FRAME\n"); frame = schro_frame_new_and_alloc(NULL, priv->frame_format, s->data.video.format.frame_width, s->data.video.format.frame_height); schro_decoder_add_output_picture (priv->dec, frame); // fprintf(stderr, "Need frame %p\n", frame); break; case SCHRO_DECODER_OK: // pic_num = schro_decoder_get_picture_number(priv->dec); /* Pull a frame out of the decoder. */ // fprintf(stderr, "State: SCHRO_DECODER_OK %d\n", // schro_decoder_get_picture_number(priv->dec)); // if(codec->dec_delay) // { priv->dec_frame = schro_decoder_pull(priv->dec); // fprintf(stderr, "Got frame %p\n", priv->dec_frame); return GAVL_SOURCE_OK; // } break; case SCHRO_DECODER_EOS: // fprintf(stderr, "State: SCHRO_DECODER_EOS\n"); // p_schro_params->eos_pulled = 1; // schro_decoder_reset (decoder); // outer = 0; return GAVL_SOURCE_EOF; break; case SCHRO_DECODER_ERROR: // fprintf(stderr, "State: SCHRO_DECODER_ERROR\n"); return GAVL_SOURCE_EOF; break; } } return GAVL_SOURCE_EOF; }
static bool RunTest(int bit_depth) { bool result = true; const int seq_len = 5; const int width = 100; const int height = 10; int luma_min = 16; int luma_max = 235; int chroma_zero = 128; schro_init(); // set up encoder SchroEncoder *encoder = schro_encoder_new(); schro_encoder_setting_set_double(encoder, "gop_structure", SCHRO_ENCODER_GOP_INTRA_ONLY); schro_encoder_setting_set_double(encoder, "rate_control", SCHRO_ENCODER_RATE_CONTROL_LOSSLESS); //schro_encoder_setting_set_double(encoder, "force_profile", SCHRO_ENCODER_PROFILE_VC2_SIMPLE); //schro_encoder_setting_set_double(encoder, "queue_depth", seq_len); //assert(seq_len <= SCHRO_LIMIT_FRAME_QUEUE_LENGTH); SchroVideoFormat *format = schro_encoder_get_video_format(encoder); if(format) { format->width = width; format->height = height; format->clean_width = format->width; format->clean_height = format->height; format->left_offset = 0; format->top_offset = 0; format->chroma_format = SCHRO_CHROMA_444; const SchroSignalRange range = (bit_depth == 12 ? SCHRO_SIGNAL_RANGE_12BIT_VIDEO : bit_depth == 10 ? SCHRO_SIGNAL_RANGE_10BIT_VIDEO : SCHRO_SIGNAL_RANGE_8BIT_VIDEO); schro_video_format_set_std_signal_range(format, range); luma_min = format->luma_offset; luma_max = format->luma_offset + format->luma_excursion; chroma_zero = format->chroma_offset; format->colour_primaries = SCHRO_COLOUR_PRIMARY_HDTV; format->colour_matrix = SCHRO_COLOUR_MATRIX_HDTV; format->transfer_function = SCHRO_TRANSFER_CHAR_TV_GAMMA; format->interlaced = false; format->frame_rate_numerator = 24; format->frame_rate_denominator = 1; format->aspect_ratio_numerator = 1; format->aspect_ratio_denominator = 1; schro_encoder_set_video_format(encoder, format); free(format); } else return false; schro_encoder_start(encoder); // create frame SchroFrame *start_frame = schro_frame_new_and_alloc(NULL, SCHRO_FRAME_FORMAT_U8_444, width, height); FillFrame<unsigned char>(start_frame, 16, 235, 128); const SchroFrameFormat schro_format = (bit_depth > 8 ? SCHRO_FRAME_FORMAT_S16_444 : SCHRO_FRAME_FORMAT_U8_444); SchroFrame *original_frame = schro_frame_new_and_alloc(NULL, schro_format, width, height); schro_frame_convert(original_frame, start_frame); SchroDecoder *decoder = schro_decoder_new(); // push frames to encoder for(int t = 0; t < seq_len; t++) { SchroFrame *new_frame = schro_frame_dup(original_frame); schro_encoder_push_frame(encoder, new_frame); } // pull packets out of encoder, pass to decoder int packets_out = 0; while(packets_out < seq_len) { SchroStateEnum encoder_state = schro_encoder_wait(encoder); if(encoder_state == SCHRO_STATE_HAVE_BUFFER || encoder_state == SCHRO_STATE_END_OF_STREAM) { int n_decodable_frames = -1; SchroBuffer *buffer = schro_encoder_pull(encoder, &n_decodable_frames); if(buffer) { const int parse_code = buffer->data[4]; if(SCHRO_PARSE_CODE_IS_SEQ_HEADER(parse_code) || SCHRO_PARSE_CODE_IS_AUXILIARY_DATA(parse_code) || SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { schro_decoder_push(decoder, buffer); //schro_buffer_unref(buffer); if(SCHRO_PARSE_CODE_IS_PICTURE(parse_code)) { packets_out++; } } } } else { assert(encoder_state == SCHRO_STATE_NEED_FRAME); assert(encoder_state != SCHRO_STATE_AGAIN); // yeah, redundant schro_encoder_end_of_stream(encoder); } } // pull frames out of decoder int frames_out = 0; while(frames_out < seq_len) { int decoder_state = schro_decoder_wait(decoder); if(decoder_state == SCHRO_DECODER_FIRST_ACCESS_UNIT) { SchroVideoFormat *format = schro_decoder_get_video_format(decoder); if(format) { assert(format->width == width); assert(format->height == height); assert(format->chroma_format == SCHRO_CHROMA_444); assert(format->luma_offset == luma_min); assert(format->luma_offset + format->luma_excursion == luma_max); assert(format->chroma_offset = chroma_zero); free(format); } } else if(decoder_state == SCHRO_DECODER_NEED_BITS) { schro_decoder_push_end_of_stream(decoder); } else if(decoder_state == SCHRO_DECODER_NEED_FRAME) { SchroFrame *decoder_frame = schro_frame_new_and_alloc(NULL, schro_format, width, height); schro_decoder_add_output_picture(decoder, decoder_frame); } else if(decoder_state == SCHRO_DECODER_OK || decoder_state == SCHRO_DECODER_EOS) { SchroFrame *decoder_frame = schro_decoder_pull(decoder); if(decoder_frame) { frames_out++; bool match = CompareFrames(decoder_frame, original_frame); //std::cout << (match ? "Match!" : "No Match!") << " " << std::endl; if(!match) { // output doesn't match input, so print the values of the // first line of the first component to see what went in and out PrintFirstLine(original_frame); std::cout << "==========" << std::endl; PrintFirstLine(decoder_frame); std::cout << "==========" << std::endl; result = false; } schro_frame_unref(decoder_frame); } } } schro_frame_unref(original_frame); schro_frame_unref(start_frame); schro_decoder_free(decoder); schro_encoder_free(encoder); return result; }
static GstFlowReturn gst_schro_dec_process_buffer (GstSchroDec *schro_dec, SchroBuffer *input_buffer) { GstFlowReturn ret = GST_FLOW_OK; SchroFrame *frame; int size; int earliest_frame; GstBuffer *outbuf; int go = 1; if (input_buffer) { ret = schro_decoder_push (schro_dec->decoder, input_buffer); if (ret == SCHRO_DECODER_FIRST_ACCESS_UNIT) { handle_first_access_unit (schro_dec); } } else { ret = schro_decoder_push_end_of_stream (schro_dec->decoder); } if (schro_dec->have_access_unit) { earliest_frame = gst_util_uint64_scale ( schro_dec->earliest_time - schro_dec->segment.start, schro_dec->fps_n, schro_dec->fps_d * GST_SECOND); GST_DEBUG("earliest frame %d", earliest_frame); schro_decoder_set_earliest_frame (schro_dec->decoder, earliest_frame); schro_decoder_set_skip_ratio (schro_dec->decoder, 1/schro_dec->proportion); } while (go) { int it; it = schro_decoder_wait (schro_dec->decoder); switch (it) { case SCHRO_DECODER_FIRST_ACCESS_UNIT: handle_first_access_unit (schro_dec); break; case SCHRO_DECODER_NEED_BITS: go = 0; break; case SCHRO_DECODER_NEED_FRAME: size = get_buffer_size (schro_dec); ret = gst_pad_alloc_buffer_and_set_caps (schro_dec->srcpad, GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (schro_dec->srcpad), &outbuf); if (ret != GST_FLOW_OK) { GST_DEBUG("could not allocate buffer for pad"); return ret; } frame = gst_schro_wrap_frame (schro_dec, outbuf); schro_decoder_add_output_picture (schro_dec->decoder, frame); break; case SCHRO_DECODER_OK: frame = schro_decoder_pull (schro_dec->decoder); if (frame) { if (frame->priv) { outbuf = frame->priv; if (schro_dec->discont) { GST_DEBUG("discont timestamp %" G_GINT64_FORMAT, GST_BUFFER_TIMESTAMP(outbuf)); GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); schro_dec->discont = FALSE; } GST_BUFFER_TIMESTAMP(outbuf) = gst_util_uint64_scale ( schro_dec->n_frames, schro_dec->fps_d * GST_SECOND, schro_dec->fps_n) + schro_dec->timestamp_offset; GST_BUFFER_DURATION(outbuf) = gst_util_uint64_scale_int (GST_SECOND, schro_dec->fps_d, schro_dec->fps_n); gst_buffer_ref(outbuf); ret = gst_pad_push (schro_dec->srcpad, outbuf); if (ret != GST_FLOW_OK) return ret; } else { GST_DEBUG("skipped frame %d", schro_dec->n_frames); } schro_dec->n_frames++; schro_frame_unref (frame); } break; case SCHRO_DECODER_EOS: go = FALSE; break; case SCHRO_DECODER_ERROR: go = FALSE; GST_ERROR ("codec error"); ret = GST_FLOW_ERROR; break; } } return ret; }
void decode (FILE *file) { SchroDecoder *decoder; SchroBuffer *buffer; SchroVideoFormat *format = NULL; SchroFrame *frame; int go; int it; int eos = FALSE; void *packet; int size; int ret; decoder = schro_decoder_new(); while(!eos) { ret = parse_packet (file, &packet, &size); if (!ret) { exit(1); } if (size == 0) { schro_decoder_push_end_of_stream (decoder); } else { buffer = schro_buffer_new_with_data (packet, size); buffer->free = buffer_free; buffer->priv = packet; it = schro_decoder_push (decoder, buffer); if (it == SCHRO_DECODER_FIRST_ACCESS_UNIT) { format = schro_decoder_get_video_format (decoder); } } go = 1; while (go) { it = schro_decoder_wait (decoder); switch (it) { case SCHRO_DECODER_NEED_BITS: go = 0; break; case SCHRO_DECODER_NEED_FRAME: frame = schro_frame_new_and_alloc (NULL, schro_params_get_frame_format(8, format->chroma_format), format->width, format->height); schro_decoder_add_output_picture (decoder, frame); break; case SCHRO_DECODER_OK: frame = schro_decoder_pull (decoder); //printf("got frame %p\n", frame); if (frame) { //printf("picture number %d\n", // schro_decoder_get_picture_number (decoder) - 1); schro_frame_unref (frame); } break; case SCHRO_DECODER_EOS: printf("got eos\n"); eos = TRUE; go = 0; break; case SCHRO_DECODER_ERROR: exit(0); break; } } } printf("freeing decoder\n"); schro_decoder_free (decoder); free(format); }