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;
}
Exemple #2
0
int
main (int argc, char *argv[])
{
  enum { HELP_OPTION = CHAR_MAX + 1 };
  static const char *options = "V";
  static const struct option long_options[] = {
    { "help", 0, 0, HELP_OPTION },
    { "compat-1.24.0", 0, 0, 0 },
    { "compat-1.24.1", 0, 0, 0 },
    { "version", 0, 0, 'V' },
    { 0, 0, 0, 0 }
  };
  int c;
  int option_index;
  int compat_1_24_0 = 0;
  int compat_1_24_1 = 0;
  const char *input;
  struct section *sections;
  struct parse_context context;
  FILE *in;
  int ret;

  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEBASEDIR);
  textdomain (PACKAGE);

  parse_context_init (&context);

  for (;;) {
    c = getopt_long (argc, argv, options, long_options, &option_index);
    if (c == -1) break;

    switch (c) {
    case 0:                     /* options which are long only */
      if (STREQ (long_options[option_index].name, "compat-1.24.0"))
        compat_1_24_0 = compat_1_24_1 = 1;
      else if (STREQ (long_options[option_index].name, "compat-1.24.1"))
        compat_1_24_1 = 1;
      else {
        fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
                 guestfs_int_program_name, long_options[option_index].name, option_index);
        exit (EXIT_FAILURE);
      }
      break;

    case 'V':
      printf ("%s %s%s\n",
              guestfs_int_program_name,
              PACKAGE_VERSION, PACKAGE_VERSION_EXTRA);
      exit (EXIT_SUCCESS);

    case HELP_OPTION:
      usage (EXIT_SUCCESS);

    default:
      usage (EXIT_FAILURE);
    }
  }

  if (optind != argc-1)
    usage (EXIT_FAILURE);

  input = argv[optind++];

  in = fopen (input, "r");
  if (in == NULL) {
    perror (input);
    exit (EXIT_FAILURE);
  }

  ret = do_parse (&context, in);

  if (fclose (in) == EOF) {
    fprintf (stderr, _("%s: %s: error closing input file: %m (ignored)\n"),
             guestfs_int_program_name, input);
  }

  if (ret != 0) {
    parse_context_free (&context);
    fprintf (stderr, _("%s: '%s' could not be validated, see errors above\n"),
             guestfs_int_program_name, input);
    exit (EXIT_FAILURE);
  }

  if (compat_1_24_1 && context.seen_comments) {
    parse_context_free (&context);
    fprintf (stderr, _("%s: %s contains comments which will not work with virt-builder 1.24.1\n"),
             guestfs_int_program_name, input);
    exit (EXIT_FAILURE);
  }

  /* Iterate over the parsed sections, semantically validating it. */
  for (sections = context.parsed_index; sections != NULL; sections = sections->next) {
    int seen_sig = 0;
    struct field *fields;

    if (compat_1_24_0) {
      if (strchr (sections->name, '_')) {
        parse_context_free (&context);
        fprintf (stderr, _("%s: %s: section [%s] has invalid characters which will not work with virt-builder 1.24.0\n"),
                 guestfs_int_program_name, input, sections->name);
        exit (EXIT_FAILURE);
      }
    }

    for (fields = sections->fields; fields != NULL; fields = fields->next) {
      if (compat_1_24_0) {
        if (strchr (fields->key, '[') ||
            strchr (fields->key, ']')) {
          parse_context_free (&context);
          fprintf (stderr, _("%s: %s: section [%s], field '%s' has invalid characters which will not work with virt-builder 1.24.0\n"),
                   guestfs_int_program_name, input, sections->name, fields->key);
          exit (EXIT_FAILURE);
        }
      }
      if (compat_1_24_1) {
        if (strchr (fields->key, '.') ||
            strchr (fields->key, ',')) {
          parse_context_free (&context);
          fprintf (stderr, _("%s: %s: section [%s], field '%s' has invalid characters which will not work with virt-builder 1.24.1\n"),
                   guestfs_int_program_name, input, sections->name, fields->key);
          exit (EXIT_FAILURE);
        }
      }
      if (STREQ (fields->key, "sig"))
        seen_sig = 1;
    }

    if (compat_1_24_0 && !seen_sig) {
      parse_context_free (&context);
      fprintf (stderr, _("%s: %s: section [%s] is missing a 'sig' field which will not work with virt-builder 1.24.0\n"),
               guestfs_int_program_name, input, sections->name);
      exit (EXIT_FAILURE);
    }
  }

  /* Free the parsed data. */
  parse_context_free (&context);

  printf ("%s validated OK\n", input);

  exit (EXIT_SUCCESS);
}