Exemple #1
0
/**
 *
 * @return the removed picture or NULL if an error occurs
 */
static Picture *remove_short(H264Context *h, int frame_num, int ref_mask)
{
    Picture *pic;
    int i;

    if (h->avctx->debug & FF_DEBUG_MMCO)
        av_log(h->avctx, AV_LOG_DEBUG, "remove short %d count %d\n", frame_num, h->short_ref_count);

    pic = find_short(h, frame_num, &i);
    if (pic) {
        if (unreference_pic(h, pic, ref_mask))
            remove_short_at_index(h, i);
    }

    return pic;
}
Exemple #2
0
int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count)
{
    int i, av_uninit(j);
    int pps_count;
    int current_ref_assigned = 0, err = 0;
    Picture *av_uninit(pic);

    if ((h->avctx->debug & FF_DEBUG_MMCO) && mmco_count == 0)
        av_log(h->avctx, AV_LOG_DEBUG, "no mmco here\n");

    for (i = 0; i < mmco_count; i++) {
        int av_uninit(structure), av_uninit(frame_num);
        if (h->avctx->debug & FF_DEBUG_MMCO)
            av_log(h->avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode,
                   h->mmco[i].short_pic_num, h->mmco[i].long_arg);

        if (mmco[i].opcode == MMCO_SHORT2UNUSED ||
            mmco[i].opcode == MMCO_SHORT2LONG) {
            frame_num = pic_num_extract(h, mmco[i].short_pic_num, &structure);
            pic       = find_short(h, frame_num, &j);
            if (!pic) {
                if (mmco[i].opcode != MMCO_SHORT2LONG ||
                    !h->long_ref[mmco[i].long_arg]    ||
                    h->long_ref[mmco[i].long_arg]->frame_num != frame_num) {
                    av_log(h->avctx, h->short_ref_count ? AV_LOG_ERROR : AV_LOG_DEBUG, "mmco: unref short failure\n");
                    err = AVERROR_INVALIDDATA;
                }
                continue;
            }
        }

        switch (mmco[i].opcode) {
        case MMCO_SHORT2UNUSED:
            if (h->avctx->debug & FF_DEBUG_MMCO)
                av_log(h->avctx, AV_LOG_DEBUG, "mmco: unref short %d count %d\n",
                       h->mmco[i].short_pic_num, h->short_ref_count);
            remove_short(h, frame_num, structure ^ PICT_FRAME);
            break;
        case MMCO_SHORT2LONG:
                if (h->long_ref[mmco[i].long_arg] != pic)
                    remove_long(h, mmco[i].long_arg, 0);

                remove_short_at_index(h, j);
                h->long_ref[ mmco[i].long_arg ] = pic;
                if (h->long_ref[mmco[i].long_arg]) {
                    h->long_ref[mmco[i].long_arg]->long_ref = 1;
                    h->long_ref_count++;
                }
            break;
        case MMCO_LONG2UNUSED:
            j   = pic_num_extract(h, mmco[i].long_arg, &structure);
            pic = h->long_ref[j];
            if (pic) {
                remove_long(h, j, structure ^ PICT_FRAME);
            } else if (h->avctx->debug & FF_DEBUG_MMCO)
                av_log(h->avctx, AV_LOG_DEBUG, "mmco: unref long failure\n");
            break;
        case MMCO_LONG:
                    // Comment below left from previous code as it is an interresting note.
                    /* First field in pair is in short term list or
                     * at a different long term index.
                     * This is not allowed; see 7.4.3.3, notes 2 and 3.
                     * Report the problem and keep the pair where it is,
                     * and mark this field valid.
                     */
            if (h->short_ref[0] == h->cur_pic_ptr) {
                av_log(h->avctx, AV_LOG_ERROR, "mmco: cannot assign current picture to short and long at the same time\n");
                remove_short_at_index(h, 0);
            }

            if (h->long_ref[mmco[i].long_arg] != h->cur_pic_ptr) {
                if (h->cur_pic_ptr->long_ref) {
                    for(j=0; j<16; j++) {
                        if(h->long_ref[j] == h->cur_pic_ptr) {
                            remove_long(h, j, 0);
                            av_log(h->avctx, AV_LOG_ERROR, "mmco: cannot assign current picture to 2 long term references\n");
                        }
                    }
                }
                av_assert0(!h->cur_pic_ptr->long_ref);
                remove_long(h, mmco[i].long_arg, 0);

                h->long_ref[mmco[i].long_arg]           = h->cur_pic_ptr;
                h->long_ref[mmco[i].long_arg]->long_ref = 1;
                h->long_ref_count++;
            }

            h->cur_pic_ptr->reference |= h->picture_structure;
            current_ref_assigned = 1;
            break;
        case MMCO_SET_MAX_LONG:
            assert(mmco[i].long_arg <= 16);
            // just remove the long term which index is greater than new max
            for (j = mmco[i].long_arg; j < 16; j++) {
                remove_long(h, j, 0);
            }
            break;
        case MMCO_RESET:
            while (h->short_ref_count) {
                remove_short(h, h->short_ref[0]->frame_num, 0);
            }
            for (j = 0; j < 16; j++) {
                remove_long(h, j, 0);
            }
            h->frame_num  = h->cur_pic_ptr->frame_num = 0;
            h->mmco_reset = 1;
            h->cur_pic_ptr->mmco_reset = 1;
            for (j = 0; j < MAX_DELAYED_PIC_COUNT; j++)
                h->last_pocs[j] = INT_MIN;
            break;
        default: assert(0);
        }
    }

    if (!current_ref_assigned) {
        /* Second field of complementary field pair; the first field of
         * which is already referenced. If short referenced, it
         * should be first entry in short_ref. If not, it must exist
         * in long_ref; trying to put it on the short list here is an
         * error in the encoded bit stream (ref: 7.4.3.3, NOTE 2 and 3).
         */
        if (h->short_ref_count && h->short_ref[0] == h->cur_pic_ptr) {
            /* Just mark the second field valid */
            h->cur_pic_ptr->reference = PICT_FRAME;
        } else if (h->cur_pic_ptr->long_ref) {
            av_log(h->avctx, AV_LOG_ERROR, "illegal short term reference "
                                           "assignment for second field "
                                           "in complementary field pair "
                                           "(first field is long term)\n");
            err = AVERROR_INVALIDDATA;
        } else {
            pic = remove_short(h, h->cur_pic_ptr->frame_num, 0);
            if (pic) {
                av_log(h->avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n");
                err = AVERROR_INVALIDDATA;
            }

            if (h->short_ref_count)
                memmove(&h->short_ref[1], &h->short_ref[0],
                        h->short_ref_count * sizeof(Picture*));

            h->short_ref[0] = h->cur_pic_ptr;
            h->short_ref_count++;
            h->cur_pic_ptr->reference |= h->picture_structure;
        }
    }

    if (h->long_ref_count + h->short_ref_count > FFMAX(h->sps.ref_frame_count, 1)) {

        /* We have too many reference frames, probably due to corrupted
         * stream. Need to discard one frame. Prevents overrun of the
         * short_ref and long_ref buffers.
         */
        av_log(h->avctx, AV_LOG_ERROR,
               "number of reference frames (%d+%d) exceeds max (%d; probably "
               "corrupt input), discarding one\n",
               h->long_ref_count, h->short_ref_count, h->sps.ref_frame_count);
        err = AVERROR_INVALIDDATA;

        if (h->long_ref_count && !h->short_ref_count) {
            for (i = 0; i < 16; ++i)
                if (h->long_ref[i])
                    break;

            assert(i < 16);
            remove_long(h, i, 0);
        } else {
            pic = h->short_ref[h->short_ref_count - 1];
            remove_short(h, pic->frame_num, 0);
        }
    }

    print_short_term(h);
    print_long_term(h);

    pps_count = 0;
    for (i = 0; i < FF_ARRAY_ELEMS(h->pps_buffers); i++)
        pps_count += !!h->pps_buffers[i];

    if (   err >= 0
        && h->long_ref_count==0
        && (h->short_ref_count<=2 || h->pps.ref_count[0] <= 1 && h->pps.ref_count[1] <= 1 && pps_count == 1)
        && h->pps.ref_count[0]<=2 + (h->picture_structure != PICT_FRAME)
        && h->cur_pic_ptr->f.pict_type == AV_PICTURE_TYPE_I){
        h->cur_pic_ptr->recovered |= 1;
        if(!h->avctx->has_b_frames)
            h->frame_recovered |= FRAME_RECOVERED_SEI;
    }

    return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0;
}
Exemple #3
0
int
Clp_Next(Clp_Parser *clp)
     /* Gets and parses the next argument from the argument list.
	
        If there are no more arguments, returns Clp_Done.
	If the next argument isn't an option, returns Clp_NotOption;
	the argument is stored in clp->arg.
	If the next argument is an option, returns that option's option_id.
	
	If the next argument is an unrecognizable or ambiguous option,
	an error message is given and Clp_BadOption is returned.
	
	If an option has an argument, that argument is stored in clp->arg
	and clp->have_arg is set to 1.
	Furthermore, that argument's parsed value (according to its type)
	is stored in the clp->val union.
	
	If an option needs an argument but isn't given one;
	if it doesn't need an argument but IS given one;
	or if the argument is the wrong type,
	an error message is given and Clp_BadOption is returned. */
{
  Clp_Internal *cli = clp->internal;
  Clp_Option *opt;
  Clp_ParserState clpsave;
  int complain;
  
  /** Set up clp **/
  cli->current_option = 0;
  cli->ambiguous = 0;
  
  /** Get the next argument or option **/
  if (!next_argument(clp, cli->option_processing ? 0 : 2))
    return clp->have_arg ? Clp_NotOption : Clp_Done;
  
  clp->negated = cli->whole_negated;
  if (cli->is_short)
    opt = find_short(clp, cli->text[0]);
  else
    opt = find_long(clp, cli->text);
  
  /** If there's ambiguity between long & short options, and we couldn't find
      a long option, look for a short option **/
  if (!opt && cli->could_be_short) {
    switch_to_short_argument(clp);
    opt = find_short(clp, cli->text[0]);
  }
  
  /** If we didn't find an option... **/
  if (!opt || (clp->negated && !TEST(opt, Clp_Negate))) {
    
    /* default processing for the "--" option: turn off option processing
       and return the next argument */
    if (strcmp(cli->argv[0], "--") == 0) {
      Clp_SetOptionProcessing(clp, 0);
      return Clp_Next(clp);
    }
    
    /* otherwise, report some error or other */
    if (cli->ambiguous)
      ambiguity_error(clp, cli->ambiguous, cli->ambiguous_values,
		      cli->opt, cli->option_chars,
		      "option `%s%s' is ambiguous",
		      cli->option_chars, cli->text);
    else if (cli->is_short && !cli->could_be_short)
      Clp_OptionError(clp, "unrecognized option `%s%c'",
		      cli->option_chars, cli->text[0]);
    else
      Clp_OptionError(clp, "unrecognized option `%s%s'",
		      cli->option_chars, cli->text);
    return Clp_BadOption;
  }
  
  /** Set the current option **/
  cli->current_option = opt;
  cli->current_short = cli->is_short;
  cli->negated_by_no = clp->negated && !cli->whole_negated;
  
  /** The no-argument (or should-have-no-argument) case **/
  if (clp->negated || !TEST(opt, Clp_AnyArgument)) {
    if (clp->have_arg) {
      Clp_OptionError(clp, "`%O' can't take an argument");
      return Clp_BadOption;
    } else
      return opt->option_id;
  }
  
  /** Get an argument if we need one, or if it's optional **/
  /* Sanity-check the argument type. */
  if (opt->arg_type <= 0 || opt->arg_type >= cli->nargtype
      || cli->argtype[ opt->arg_type ].func == 0)
    return Clp_Error;
  
  /* complain == 1 only if the argument was explicitly given,
     or it is mandatory. */
  complain = (clp->have_arg != 0) || TEST(opt, Clp_Mandatory);
  Clp_SaveParser(clp, &clpsave);
  
  if (TEST(opt, Clp_Mandatory) && !clp->have_arg) {
    /* Mandatory argument case */
    /* Allow arguments to options to start with a dash, but only if the
       argument type allows it by not setting Clp_DisallowOptions */
    int disallow = TEST(&cli->argtype[opt->arg_type], Clp_DisallowOptions);
    next_argument(clp, disallow ? 1 : 2);
    if (!clp->have_arg) {
      int got_option = cli->text != 0;
      Clp_RestoreParser(clp, &clpsave);
      if (got_option)
	Clp_OptionError(clp, "`%O' requires a non-option argument");
      else
	Clp_OptionError(clp, "`%O' requires an argument");
      return Clp_BadOption;
    }
    
  } else if (cli->is_short && !clp->have_arg && cli->text[1] != 0)
    /* The -[option]argument case:
       Assume that the rest of the current string is the argument. */
    next_argument(clp, 1);
  
  /** Parse the argument **/
  if (clp->have_arg) {
    Clp_ArgType *atr = &cli->argtype[ opt->arg_type ];
    if (atr->func(clp, clp->arg, complain, atr->thunk) <= 0) {
      /* parser failed */
      clp->have_arg = 0;
      if (TEST(opt, Clp_Mandatory))
	return Clp_BadOption;
      else
	Clp_RestoreParser(clp, &clpsave);
    }
  }
  
  return opt->option_id;
}
Exemple #4
0
int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
    MpegEncContext * const s = &h->s;
    int i, av_uninit(j);
    int current_ref_assigned=0;
    Picture *av_uninit(pic);

    if((s->avctx->debug&FF_DEBUG_MMCO) && mmco_count==0)
        av_log(h->s.avctx, AV_LOG_DEBUG, "no mmco here\n");

    for(i=0; i<mmco_count; i++){
        int av_uninit(structure), av_uninit(frame_num);
        if(s->avctx->debug&FF_DEBUG_MMCO)
            av_log(h->s.avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode, h->mmco[i].short_pic_num, h->mmco[i].long_arg);

        if(   mmco[i].opcode == MMCO_SHORT2UNUSED
           || mmco[i].opcode == MMCO_SHORT2LONG){
            frame_num = pic_num_extract(h, mmco[i].short_pic_num, &structure);
            pic = find_short(h, frame_num, &j);
            if(!pic){
                if(mmco[i].opcode != MMCO_SHORT2LONG || !h->long_ref[mmco[i].long_arg]
                   || h->long_ref[mmco[i].long_arg]->frame_num != frame_num)
                av_log(h->s.avctx, AV_LOG_ERROR, "mmco: unref short failure\n");
                continue;
            }
        }

        switch(mmco[i].opcode){
        case MMCO_SHORT2UNUSED:
            if(s->avctx->debug&FF_DEBUG_MMCO)
                av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref short %d count %d\n", h->mmco[i].short_pic_num, h->short_ref_count);
            remove_short(h, frame_num, structure ^ PICT_FRAME);
            break;
        case MMCO_SHORT2LONG:
                if (h->long_ref[mmco[i].long_arg] != pic)
                    remove_long(h, mmco[i].long_arg, 0);

                remove_short_at_index(h, j);
                h->long_ref[ mmco[i].long_arg ]= pic;
                if (h->long_ref[ mmco[i].long_arg ]){
                    h->long_ref[ mmco[i].long_arg ]->long_ref=1;
                    h->long_ref_count++;
                }
            break;
        case MMCO_LONG2UNUSED:
            j = pic_num_extract(h, mmco[i].long_arg, &structure);
            pic = h->long_ref[j];
            if (pic) {
                remove_long(h, j, structure ^ PICT_FRAME);
            } else if(s->avctx->debug&FF_DEBUG_MMCO)
                av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref long failure\n");
            break;
        case MMCO_LONG:
                    // Comment below left from previous code as it is an interresting note.
                    /* First field in pair is in short term list or
                     * at a different long term index.
                     * This is not allowed; see 7.4.3.3, notes 2 and 3.
                     * Report the problem and keep the pair where it is,
                     * and mark this field valid.
                     */

            if (h->long_ref[mmco[i].long_arg] != s->current_picture_ptr) {
                remove_long(h, mmco[i].long_arg, 0);

                h->long_ref[ mmco[i].long_arg ]= s->current_picture_ptr;
                h->long_ref[ mmco[i].long_arg ]->long_ref=1;
                h->long_ref_count++;
            }

            s->current_picture_ptr->reference |= s->picture_structure;
            current_ref_assigned=1;
            break;
        case MMCO_SET_MAX_LONG:
            assert(mmco[i].long_arg <= 16);
            // just remove the long term which index is greater than new max
            for(j = mmco[i].long_arg; j<16; j++){
                remove_long(h, j, 0);
            }
            break;
        case MMCO_RESET:
            while(h->short_ref_count){
                remove_short(h, h->short_ref[0]->frame_num, 0);
            }
            for(j = 0; j < 16; j++) {
                remove_long(h, j, 0);
            }
            s->current_picture_ptr->poc=
            s->current_picture_ptr->field_poc[0]=
            s->current_picture_ptr->field_poc[1]=
            h->poc_lsb=
            h->poc_msb=
            h->frame_num=
            s->current_picture_ptr->frame_num= 0;
            s->current_picture_ptr->mmco_reset=1;
            break;
        default: assert(0);
        }
    }

    if (!current_ref_assigned) {
        /* Second field of complementary field pair; the first field of
         * which is already referenced. If short referenced, it
         * should be first entry in short_ref. If not, it must exist
         * in long_ref; trying to put it on the short list here is an
         * error in the encoded bit stream (ref: 7.4.3.3, NOTE 2 and 3).
         */
        if (h->short_ref_count && h->short_ref[0] == s->current_picture_ptr) {
            /* Just mark the second field valid */
            s->current_picture_ptr->reference = PICT_FRAME;
        } else if (s->current_picture_ptr->long_ref) {
            av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term reference "
                                             "assignment for second field "
                                             "in complementary field pair "
                                             "(first field is long term)\n");
        } else {
            pic= remove_short(h, s->current_picture_ptr->frame_num, 0);
            if(pic){
                av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n");
            }

            if(h->short_ref_count)
                memmove(&h->short_ref[1], &h->short_ref[0], h->short_ref_count*sizeof(Picture*));

            h->short_ref[0]= s->current_picture_ptr;
            h->short_ref_count++;
            s->current_picture_ptr->reference |= s->picture_structure;
        }
    }

    if (h->long_ref_count + h->short_ref_count > FFMAX(h->sps.ref_frame_count, 1)){

        /* We have too many reference frames, probably due to corrupted
         * stream. Need to discard one frame. Prevents overrun of the
         * short_ref and long_ref buffers.
         */
        av_log(h->s.avctx, AV_LOG_ERROR,
               "number of reference frames (%d+%d) exceeds max (%d; probably "
               "corrupt input), discarding one\n",
               h->long_ref_count, h->short_ref_count, h->sps.ref_frame_count);

        if (h->long_ref_count && !h->short_ref_count) {
            for (i = 0; i < 16; ++i)
                if (h->long_ref[i])
                    break;

            assert(i < 16);
            remove_long(h, i, 0);
        } else {
            pic = h->short_ref[h->short_ref_count - 1];
            remove_short(h, pic->frame_num, 0);
        }
    }

    print_short_term(h);
    print_long_term(h);
    return 0;
}
Exemple #5
0
UpoptStatus
upopt_next(UpoptContext* context, int* constant, const char** value, char** error)
{
    const char* arg;
    const char* val = NULL;
    const UpoptOptionInfo* info = NULL;
   
    if (context->index >= context->argc)
        return UPOPT_STATUS_DONE;

    arg = context->argv[context->index++];

    if (!context->only_normal)
    {
        if (is_long(arg))
        {
            if (!arg[2])
            {
                context->only_normal = 1;
                return upopt_next(context, constant, value, error);
            }
            else
            {
                char* equal = strchr(arg, '=');
                
                if (equal)
                {
                    *equal = '\0';
                    val = equal + 1;
                }
                
                info = find_long(context->options, arg+2);
                
                if (equal)
                {
                    *equal = '=';
                }
                
                if (!info)
                {
                    *error = format("Unrecognized option: %s\n", arg);
                    return UPOPT_STATUS_ERROR;
                }
            }
        }
        else if (is_short(arg))
        {
            if (arg[2])
            {
                val = arg+2;
            }

            info = find_short(context->options, arg[1]);
            
            if (!info)
            {
                *error = format("Unrecognized option: %s\n", arg);
                return UPOPT_STATUS_ERROR;
            }
        }
    }
     
    if (info)
    {
        if (val && !info->argument)
        {
            if (is_long(arg))
            {
                *error = format("Did not expect an argument after --%s\n", 
                                info->longname);
            }
            else
            {
                *error = format("Did not expect an argument after -%c\n", 
                                info->shortname);
            }
            return UPOPT_STATUS_ERROR;
        }
        else if (!val && info->argument)
        {
            if ((context->index >= context->argc ||
                 (!context->only_normal &&
                  is_option(context->argv[context->index]))))
            {
                *error = format("Expected argument after %s\n", arg);
                return UPOPT_STATUS_ERROR;
            }
            val = context->argv[context->index++];
        }

        *constant = info->constant;
        *value = val;
        *error = NULL;
        return UPOPT_STATUS_NORMAL;
    }
    else
    {
        *constant = UPOPT_ARG_NORMAL;
        *value = arg;
        *error = NULL;
        return UPOPT_STATUS_NORMAL;
    }
}