/** * * @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; }
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; }
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; }
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; }
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; } }