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 *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;
}
Example #3
0
static void
handle_packet (unsigned char *data, int size)
{
  SchroUnpack unpack;
  const char *parse_code;
  int next;
  int prev;

  if (memcmp (data, "BBCD", 4) != 0) {
    printf("non-Dirac packet\n");
    dump_hex (data, MIN(size, 100), "  ");
    return;
  }

  switch (data[4]) {
    case SCHRO_PARSE_CODE_SEQUENCE_HEADER:
      parse_code = "access unit header";
      break;
    case SCHRO_PARSE_CODE_AUXILIARY_DATA:
      parse_code = "auxiliary data";
      break;
    case SCHRO_PARSE_CODE_INTRA_REF:
      parse_code = "intra ref";
      break;
    case SCHRO_PARSE_CODE_INTRA_NON_REF:
      parse_code = "intra non-ref";
      break;
    case SCHRO_PARSE_CODE_INTER_REF_1:
      parse_code = "inter ref 1";
      break;
    case SCHRO_PARSE_CODE_INTER_REF_2:
      parse_code = "inter ref 2";
      break;
    case SCHRO_PARSE_CODE_INTER_NON_REF_1:
      parse_code = "inter non-ref 1";
      break;
    case SCHRO_PARSE_CODE_INTER_NON_REF_2:
      parse_code = "inter non-ref 2";
      break;
    case SCHRO_PARSE_CODE_END_OF_SEQUENCE:
      parse_code = "end of sequence";
      break;
    case SCHRO_PARSE_CODE_LD_INTRA_REF:
      parse_code = "low-delay intra ref";
      break;
    case SCHRO_PARSE_CODE_LD_INTRA_NON_REF:
      parse_code = "low-delay intra non-ref";
      break;
    case SCHRO_PARSE_CODE_INTRA_REF_NOARITH:
      parse_code = "intra ref noarith";
      break;
    case SCHRO_PARSE_CODE_INTRA_NON_REF_NOARITH:
      parse_code = "intra non-ref noarith";
      break;
    case SCHRO_PARSE_CODE_INTER_REF_1_NOARITH:
      parse_code = "inter ref 1 noarith";
      break;
    case SCHRO_PARSE_CODE_INTER_REF_2_NOARITH:
      parse_code = "inter ref 2 noarith";
      break;
    case SCHRO_PARSE_CODE_INTER_NON_REF_1_NOARITH:
      parse_code = "inter non-ref 1 noarith";
      break;
    case SCHRO_PARSE_CODE_INTER_NON_REF_2_NOARITH:
      parse_code = "inter non-ref 2 noarith";
      break;
    default:
      parse_code = "unknown";
      break;
  }
  schro_unpack_init_with_data (&unpack, data + 5, size - 5, 1);

  next = schro_unpack_decode_bits (&unpack, 32);
  prev = schro_unpack_decode_bits (&unpack, 32);

  if (data[4] == SCHRO_PARSE_CODE_SEQUENCE_HEADER) {
    printf("AU\n");
    printf("pictur: ");
    printf("    ");
    printf("  ");
    printf("  ref1 ");
    printf("  ref2 ");
    printf("retire ");
    printf("     size \n");
  } else if (SCHRO_PARSE_CODE_IS_PICTURE(data[4])) {
    int num_refs = SCHRO_PARSE_CODE_NUM_REFS(data[4]);
    int pic_num;
    char ref_chars[3] = { 'I', 'P', 'B' };

    schro_unpack_byte_sync(&unpack);
    pic_num = schro_unpack_decode_bits(&unpack, 32);
    printf("%6d: ", pic_num);
    if (SCHRO_PARSE_CODE_IS_REFERENCE(data[4])) {
      printf("ref ");
    } else {
      printf("    ");
    }

    printf("%c ", ref_chars[num_refs]);

    if (num_refs > 0) {
      printf("%6d ", pic_num + schro_unpack_decode_sint(&unpack));
    } else {
      printf("       ");
    }
    if (num_refs > 1) {
      printf("%6d ", pic_num + schro_unpack_decode_sint(&unpack));
    } else {
      printf("       ");
    }

    if (SCHRO_PARSE_CODE_IS_REFERENCE(data[4])) {
      int r = schro_unpack_decode_sint(&unpack);
      if (r == 0) {
        printf("  none ");
      } else {
        printf("%6d ", pic_num + r);
      }
    } else {
      printf("       ");
    }
    printf(" %8d\n", next);
  } else if (data[4] == SCHRO_PARSE_CODE_AUXILIARY_DATA) {
  }

  schro_unpack_byte_sync (&unpack);
}