/*! ************************************************************************ * \brief * Write out not paired direct output fields. A second empty field is generated * and combined into the frame buffer. * \param fs * FrameStore that contains a single field * \param p_out * Output file ************************************************************************ */ void write_unpaired_field(FrameStore* fs, FILE *p_out) { StorablePicture *p; assert (fs->is_used<3); if(fs->is_used &1) { // we have a top field // construct an empty bottom field p = fs->top_field; fs->bottom_field = alloc_storable_picture(BOTTOM_FIELD, p->size_x, p->size_y, p->size_x_cr, p->size_y_cr); clear_picture(fs->bottom_field); dpb_combine_field(fs); write_picture (fs->frame, p_out); fs->is_used=3; } if(fs->is_used &2) { // we have a bottom field // construct an empty top field p = fs->bottom_field; fs->top_field = alloc_storable_picture(TOP_FIELD, p->size_x, p->size_y, p->size_x_cr, p->size_y_cr); clear_picture(fs->bottom_field); dpb_combine_field(fs); write_picture (fs->frame, p_out); fs->is_used=3; } }
/*! ************************************************************************ * \brief * Directly output a picture without storing it in the DPB. Fields * are buffered before they are written to the file. * \param p * Picture for output * \param p_out * Output file ************************************************************************ */ void direct_output(StorablePicture *p, FILE *p_out) { if (p->structure==FRAME) { // we have a frame (or complementary field pair) // so output it directly flush_direct_output(p_out); write_picture (p, p_out, FRAME); if (p_ref) find_snr(snr, p, p_ref); free_storable_picture(p); return; } if (p->structure == TOP_FIELD) { if (out_buffer->is_used &1) flush_direct_output(p_out); out_buffer->top_field = p; out_buffer->is_used |= 1; } if (p->structure == BOTTOM_FIELD) { if (out_buffer->is_used &2) flush_direct_output(p_out); out_buffer->bottom_field = p; out_buffer->is_used |= 2; } if (out_buffer->is_used == 3) { // we have both fields, so output them dpb_combine_field(out_buffer); write_picture (out_buffer->frame, p_out, FRAME); if (p_ref) find_snr(snr, out_buffer->frame, p_ref); free_storable_picture(out_buffer->frame); out_buffer->frame = NULL; free_storable_picture(out_buffer->top_field); out_buffer->top_field = NULL; free_storable_picture(out_buffer->bottom_field); out_buffer->bottom_field = NULL; out_buffer->is_used = 0; } }
/*! ************************************************************************ * \brief * Write out not paired direct output fields. A second empty field is generated * and combined into the frame buffer. * \param fs * FrameStore that contains a single field * \param p_out * Output file ************************************************************************ */ void write_unpaired_field(FrameStore* fs, FILE *p_out) { StorablePicture *p; assert (fs->is_used<3); if(fs->is_used &1) { // we have a top field // construct an empty bottom field p = fs->top_field; fs->bottom_field = alloc_storable_picture(BOTTOM_FIELD, p->size_x, 2*p->size_y, p->size_x_cr, 2*p->size_y_cr); clear_picture(fs->bottom_field); dpb_combine_field(fs); write_picture (fs->frame, p_out, TOP_FIELD); } if(fs->is_used &2) { // we have a bottom field // construct an empty top field p = fs->bottom_field; fs->top_field = alloc_storable_picture(TOP_FIELD, p->size_x, 2*p->size_y, p->size_x_cr, 2*p->size_y_cr); clear_picture(fs->top_field); fs ->top_field->frame_cropping_flag = fs->bottom_field->frame_cropping_flag; if(fs ->top_field->frame_cropping_flag) { fs ->top_field->frame_cropping_rect_top_offset = fs->bottom_field->frame_cropping_rect_top_offset; fs ->top_field->frame_cropping_rect_bottom_offset = fs->bottom_field->frame_cropping_rect_bottom_offset; fs ->top_field->frame_cropping_rect_left_offset = fs->bottom_field->frame_cropping_rect_left_offset; fs ->top_field->frame_cropping_rect_right_offset = fs->bottom_field->frame_cropping_rect_right_offset; } dpb_combine_field(fs); write_picture (fs->frame, p_out, BOTTOM_FIELD); } fs->is_used=3; }
/*! ************************************************************************ * \brief * Write a frame (from FrameStore) * \param fs * FrameStore containing the frame * \param p_out * Output file ************************************************************************ */ void write_stored_frame( FrameStore *fs,FILE *p_out) { // make sure no direct output field is pending flush_direct_output(p_out); if (fs->is_used<3) { write_unpaired_field(fs, p_out); } else { write_picture(fs->frame, p_out); } fs->is_output = 1; }
/*! ************************************************************************ * \brief * Writes out a storable picture * If the picture is a field, the output buffers the picture and tries * to pair it with the next field. * \param p * Picture to be written * \param p_out * Output file ************************************************************************ */ void write_picture(StorablePicture *p, FILE *p_out, int real_structure) { int i, add; if (real_structure==FRAME) { flush_pending_output(p_out); write_out_picture(p, p_out); return; } if (real_structure==pending_output_state) { flush_pending_output(p_out); write_picture(p, p_out, real_structure); return; } if (pending_output_state == FRAME) { pending_output->size_x = p->size_x; pending_output->size_y = p->size_y; pending_output->size_x_cr = p->size_x_cr; pending_output->size_y_cr = p->size_y_cr; pending_output->frame_mbs_only_flag = p->frame_mbs_only_flag; pending_output->frame_cropping_flag = p->frame_cropping_flag; if (pending_output->frame_cropping_flag) { pending_output->frame_cropping_rect_left_offset = p->frame_cropping_rect_left_offset; pending_output->frame_cropping_rect_right_offset = p->frame_cropping_rect_right_offset; pending_output->frame_cropping_rect_top_offset = p->frame_cropping_rect_top_offset; pending_output->frame_cropping_rect_bottom_offset = p->frame_cropping_rect_bottom_offset; } get_mem2D (&(pending_output->imgY), pending_output->size_y, pending_output->size_x); get_mem3D (&(pending_output->imgUV), 2, pending_output->size_y_cr, pending_output->size_x_cr ); clear_picture(pending_output); // copy first field if (real_structure == TOP_FIELD) { add = 0; } else { add = 1; } for (i=0; i<pending_output->size_y; i+=2) { memcpy(pending_output->imgY[(i+add)], p->imgY[(i+add)], p->size_x); } for (i=0; i<pending_output->size_y_cr; i+=2) { memcpy(pending_output->imgUV[0][(i+add)], p->imgUV[0][(i+add)], p->size_x_cr); memcpy(pending_output->imgUV[1][(i+add)], p->imgUV[1][(i+add)], p->size_x_cr); } pending_output_state = real_structure; } else { if ( (pending_output->size_x!=p->size_x) || (pending_output->size_y!= p->size_y) || (pending_output->frame_mbs_only_flag != p->frame_mbs_only_flag) || (pending_output->frame_cropping_flag != p->frame_cropping_flag) || ( pending_output->frame_cropping_flag && ( (pending_output->frame_cropping_rect_left_offset != p->frame_cropping_rect_left_offset) ||(pending_output->frame_cropping_rect_right_offset != p->frame_cropping_rect_right_offset) ||(pending_output->frame_cropping_rect_top_offset != p->frame_cropping_rect_top_offset) ||(pending_output->frame_cropping_rect_bottom_offset != p->frame_cropping_rect_bottom_offset) ) ) ) { flush_pending_output(p_out); write_picture (p, p_out, real_structure); return; } // copy second field if (real_structure == TOP_FIELD) { add = 0; } else { add = 1; } for (i=0; i<pending_output->size_y; i+=2) { memcpy(pending_output->imgY[(i+add)], p->imgY[(i+add)], p->size_x); } for (i=0; i<pending_output->size_y_cr; i+=2) { memcpy(pending_output->imgUV[0][(i+add)], p->imgUV[0][(i+add)], p->size_x_cr); memcpy(pending_output->imgUV[1][(i+add)], p->imgUV[1][(i+add)], p->size_x_cr); } flush_pending_output(p_out); } }