📄 fame_profile_mpeg.c
字号:
/* *//* Description: *//* Encode a single slice. *//* *//* Arguments: *//* fame_profile_t * profile: the profile handle returned by fame_open *//* *//* Return value: *//* int : the number of bytes written to buffer */static int profile_mpeg_encode(fame_profile_t *profile){ fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile); int x, y; int slice_end; /* the 4 Y and 2 C blocks in a macroblock */ short * blocks[6]; /* the binary alpha block */ unsigned char *bab; fame_bab_t bab_type; fame_motion_coding_t motion_coding; fame_motion_vector_t forward[6]; unsigned char pattern; int dquant; int mv_count = 0; int mv_norm = 0; int quant_sum = 0; /* Test for end of frame */ if(profile_mpeg->slice_start >= (profile_mpeg->height >> 4)) return(0); /* Clear syntax buffer */ if(profile_mpeg->slice_start != 0) { if(profile_mpeg->syntax && profile_mpeg->syntax->use) profile_mpeg->syntax->use(profile_mpeg->syntax, profile_mpeg->buffer, profile_mpeg->dirty); profile_mpeg->dirty = 0; } bab_type = bab_all_coded; motion_coding = motion_intra; pattern = 0x0f; /* all blocks coded */ /* Generate slice */ if(profile_mpeg->syntax && profile_mpeg->syntax->start_slice) profile_mpeg->syntax->start_slice(profile_mpeg->syntax, profile_mpeg->slice_start, profile_mpeg->lines_per_slice* (profile_mpeg->width>>4), profile_mpeg->quant_scale); slice_end = fame_min(profile_mpeg->height >> 4, profile_mpeg->slice_start+profile_mpeg->lines_per_slice); /* Encode macroblocks */ for (y = profile_mpeg->slice_start; y < slice_end; y++) for (x = 0; x < (profile_mpeg->width >> 4); x++) { /* code shape */ if(profile_mpeg->shape && profile_mpeg->shape->encode_intra_shape) bab_type = profile_mpeg->shape->encode_intra_shape(profile_mpeg->shape, x, y, &bab, &pattern); /* compensate motion */ if(profile_mpeg->current_coding == 'P') { if(profile_mpeg->syntax && profile_mpeg->syntax->predict_vector) profile_mpeg->syntax->predict_vector(profile_mpeg->syntax, x, y, 0, forward); if(profile_mpeg->motion && profile_mpeg->motion->estimation) motion_coding = profile_mpeg->motion->estimation(profile_mpeg->motion, x, y, forward, profile_mpeg->quant_scale); /* U and V vectors */ if(profile_mpeg->syntax && profile_mpeg->syntax->compute_chrominance_vectors) profile_mpeg->syntax->compute_chrominance_vectors(profile_mpeg->syntax, forward, pattern); } else motion_coding = motion_intra; /* adaptive quantization */ if(profile_mpeg->rate && profile_mpeg->rate->local_estimation) dquant = profile_mpeg->rate->local_estimation(profile_mpeg->rate, x, y, blocks, motion_coding); else dquant = 0; if(motion_coding == motion_intra) { profile_mpeg->intra++; /* Code intra macroblock */ if(profile_mpeg->encoder && profile_mpeg->encoder->encode_intra_mb && bab_type != bab_not_coded) profile_mpeg->encoder->encode_intra_mb(profile_mpeg->encoder, x, y, blocks, profile_mpeg->quant_scale, bab_type); if(profile_mpeg->next_coding != 'I') if(profile_mpeg->decoder && profile_mpeg->decoder->reconstruct_intra_mb && bab_type != bab_not_coded) profile_mpeg->decoder->reconstruct_intra_mb(profile_mpeg->decoder, x, y, blocks, profile_mpeg->quant_scale, bab_type); /* Write macroblock */ if(profile_mpeg->syntax && profile_mpeg->syntax->write_intra_mb) profile_mpeg->quant_scale -= /* dquant may be cancelled */ profile_mpeg->syntax->write_intra_mb(profile_mpeg->syntax, x, y, blocks, bab, profile_mpeg->bab_map, bab_type, dquant, pattern); } else { profile_mpeg->inter++; /* TODO: check for coded in syntax macroblock depending on error */ /* of motion estimation, for inter blocks only. */ if(profile_mpeg->search_range_adaptive) { if(motion_coding == motion_inter4v) { mv_count += 4; mv_norm += forward[0].dx*forward[0].dx + forward[0].dy*forward[0].dy; mv_norm += forward[1].dx*forward[1].dx + forward[1].dy*forward[1].dy; mv_norm += forward[2].dx*forward[2].dx + forward[2].dy*forward[2].dy; mv_norm += forward[3].dx*forward[3].dx + forward[3].dy*forward[3].dy; } else { mv_count++; mv_norm += forward[0].dx*forward[0].dx + forward[0].dy*forward[0].dy; } } /* Code inter macroblock */ if(profile_mpeg->encoder && profile_mpeg->encoder->encode_inter_mb && bab_type != bab_not_coded) profile_mpeg->encoder->encode_inter_mb(profile_mpeg->encoder, x, y, blocks, forward, NULL, motion_coding, profile_mpeg->quant_scale, bab_type); if(profile_mpeg->next_coding != 'I') if(profile_mpeg->decoder && profile_mpeg->decoder->reconstruct_inter_mb && bab_type != bab_not_coded) profile_mpeg->decoder->reconstruct_inter_mb(profile_mpeg->decoder, x, y, blocks, forward, NULL, motion_coding, profile_mpeg->quant_scale, bab_type); /* Write macroblock */ if(profile_mpeg->syntax && profile_mpeg->syntax->write_inter_mb) profile_mpeg->quant_scale -= /* dquant may be cancelled */ profile_mpeg->syntax->write_inter_mb(profile_mpeg->syntax, x, y, blocks, bab, profile_mpeg->bab_map, bab_type, dquant, pattern, forward, NULL, motion_coding); } quant_sum += profile_mpeg->quant_scale; } #ifdef HAS_MMX asm("emms");#endif if(mv_count) { /* adapt search range according to MV standard deviation */ mv_norm /= mv_count; mv_norm = (int) sqrt(mv_norm); if(profile_mpeg->search_range < 3*mv_norm && profile_mpeg->search_range < 1024) { profile_mpeg->search_range <<= 1; } else if(profile_mpeg->search_range > 6*mv_norm && profile_mpeg->search_range > 16) { profile_mpeg->search_range >>= 1; } } /* End of slice */ if(profile_mpeg->syntax && profile_mpeg->syntax->end_slice) profile_mpeg->syntax->end_slice(profile_mpeg->syntax); profile_mpeg->quant_avg = (float) quant_sum / ((slice_end - profile_mpeg->slice_start) * (profile_mpeg->width >> 4)); /* Return the number of bytes encoded */ if(profile_mpeg->syntax && profile_mpeg->syntax->flush) profile_mpeg->dirty = profile_mpeg->syntax->flush(profile_mpeg->syntax); else profile_mpeg->dirty = 0; profile_mpeg->total += profile_mpeg->dirty; profile_mpeg->slice_start = slice_end; return(profile_mpeg->dirty);}/* profile_mpeg_leave *//* *//* Description: *//* Finish encoding a picture. *//* *//* Arguments: *//* fame_profile_t * profile: the profile handle returned by fame_open *//* fame_frame_statistics_t * stats: information about the encoding *//* *//* Return value: *//* None. */static void profile_mpeg_leave(fame_profile_t *profile, fame_frame_statistics_t *stats){ fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile); /* Pad and interpolate for half-pel estimation/compensation */ if(profile_mpeg->motion->flags & FAME_MOTION_FLIP_ROUNDING) profile_mpeg->rounding ^= 1; if(profile_mpeg->next_coding != 'I' && (profile_mpeg->motion->flags & FAME_MOTION_SUBPEL_SEARCH)) if(profile_mpeg->decoder && profile_mpeg->decoder->interpolate) profile_mpeg->decoder->interpolate(profile_mpeg->decoder, profile_mpeg->rounding); if(profile_mpeg->next_coding != 'I' && (profile_mpeg->shape || (profile_mpeg->motion->flags & FAME_MOTION_UNRESTRICTED_SEARCH))) if(profile_mpeg->decoder && profile_mpeg->decoder->pad) profile_mpeg->decoder->pad(profile_mpeg->decoder, profile_mpeg->bab_map, &profile_mpeg->bounding_box);#undef DEBUG_WRITE_RECONSTRUCTED_FRAMES#ifdef DEBUG_WRITE_RECONSTRUCTED_FRAMES /* Write reconstructed frame to standard output */ fwrite(profile_mpeg->ref[profile_mpeg->current][1]->y - (16*(profile_mpeg->width+32)+16), (profile_mpeg->width+32)*(profile_mpeg->height+32), 1, stdout); fwrite(profile_mpeg->ref[profile_mpeg->current][1]->u - (8*(profile_mpeg->width+32)/2+8), (profile_mpeg->width+32)*(profile_mpeg->height+32)/4, 1, stdout); fwrite(profile_mpeg->ref[profile_mpeg->current][1]->v - (8*(profile_mpeg->width+32)/2+8), (profile_mpeg->width+32)*(profile_mpeg->height+32)/4, 1, stdout);#endif /* Leave the encoder */ if(profile_mpeg->encoder && profile_mpeg->encoder->leave) profile_mpeg->encoder->leave(profile_mpeg->encoder); /* Leave the decoder */ if(profile_mpeg->decoder && profile_mpeg->decoder->leave) profile_mpeg->decoder->leave(profile_mpeg->decoder); /* Leave the motion */ if(profile_mpeg->motion && profile_mpeg->motion->leave) profile_mpeg->motion->leave(profile_mpeg->motion); /* Rotate reference ring */ switch(profile_mpeg->current_coding) { case 'I': case 'P': profile_mpeg->past = profile_mpeg->future; profile_mpeg->future = profile_mpeg->current; profile_mpeg->current = !profile_mpeg->current; break; case 'B': break; default: break; } /* Increment frame number */ profile_mpeg->frame_number++; /* Update rate control */ if(profile_mpeg->rate && profile_mpeg->rate->leave) profile_mpeg->rate->leave(profile_mpeg->rate, profile_mpeg->total * 8); /* Show picture info */ if(profile_mpeg->verbose) { if(profile_mpeg->intra+profile_mpeg->inter) { FAME_INFO("inter/intra %3d%% ", 100*profile_mpeg->inter/ (profile_mpeg->intra+profile_mpeg->inter)); } FAME_INFO("%dkbits/s quality %.02f%% range %d %c frame #%d\033[K\r", (profile_mpeg->total * profile_mpeg->fps_num * 8) / (profile_mpeg->fps_den * 1000), (31 - profile_mpeg->quant_avg) * 100 / 30, profile_mpeg->search_range, profile_mpeg->current_coding, profile_mpeg->frame_number); } if(profile_mpeg->monitor && profile_mpeg->monitor->leave) profile_mpeg->monitor->leave(profile_mpeg->monitor, profile_mpeg->total * 8, profile_mpeg->quant_avg); if(stats) *stats = *profile_mpeg->frame_stats;}/* profile_mpeg_close *//* *//* Description: *//* Flush remaining encoded data and cleanup everything. *//* *//* Arguments: *//* fame_profile_t * profile: the profile handle returned by fame_open *//* *//* Return value: *//* int : the number of bytes written to buffer */static int profile_mpeg_close(fame_profile_t *profile){ fame_profile_mpeg_t *profile_mpeg = FAME_PROFILE_MPEG(profile); int i, j; int bytes_written; /* Initialize syntax buffer */ if(profile_mpeg->syntax && profile_mpeg->syntax->use) profile_mpeg->syntax->use(profile_mpeg->syntax, profile_mpeg->buffer, profile_mpeg->dirty); /* Generate the sequence ender code */ if(profile_mpeg->syntax && profile_mpeg->syntax->end_sequence) profile_mpeg->syntax->end_sequence(profile_mpeg->syntax); /* Flush the syntax buffer */ if(profile_mpeg->syntax && profile_mpeg->syntax->flush) bytes_written = profile_mpeg->syntax->flush(profile_mpeg->syntax); else bytes_written = 0; /* Release the decoder */ if(profile_mpeg->decoder && profile_mpeg->decoder->close) profile_mpeg->decoder->close(profile_mpeg->decoder); /* Release the encoder */ if(profile_mpeg->encoder && profile_mpeg->encoder->close) profile_mpeg->encoder->close(profile_mpeg->encoder); /* Release the syntax */ if(profile_mpeg->syntax && profile_mpeg->syntax->close) profile_mpeg->syntax->close(profile_mpeg->syntax); /* Release the motion estimation */ if(profile_mpeg->motion && profile_mpeg->motion->close) profile_mpeg->motion->close(profile_mpeg->motion); /* Release the shape coder */ if(profile_mpeg->shape && profile_mpeg->shape->close) profile_mpeg->shape->close(profile_mpeg->shape); /* Release the rate controller */ if(profile_mpeg->rate && profile_mpeg->rate->close) profile_mpeg->rate->close(profile_mpeg->rate); /* Release statistics monitoring */ if(profile_mpeg->monitor && profile_mpeg->monitor->close) profile_mpeg->monitor->close(profile_mpeg->monitor); /* Free reference shape */ if(profile_mpeg->ref_shape) fame_free(profile_mpeg->ref_shape); /* Free BAB map */ if(profile_mpeg->bab_map) fame_free(profile_mpeg->bab_map); /* Free reference ring */ for(j = 0; j < 2; j++) /* 2 references */ for(i = 0; i < 4; i++) { /* 4 planes per reference (interpolation) */ /* remove offset */ profile_mpeg->ref[j][i]->y -= 16*(profile_mpeg->width+32)+16; fame_free(profile_mpeg->ref[j][i]->y); } /* Print newline for picture codes */ if(profile_mpeg->verbose) FAME_INFO("\n"); /* Return the number of bytes written to buffer */ return(bytes_written);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -