/* * Support functions for write_unblocked. * They originate from Ruby's io.c. We redefine them here * because in that file they are declared with static, so * they aren't accessible here. */ static int io_fflush(rb_io_t *fptr){ rb_io_check_closed(fptr); if (fptr->wbuf_len == 0) return 0; if (!rb_thread_fd_writable(fptr->fd)) { rb_io_check_closed(fptr); } while (fptr->wbuf_len > 0 && io_flush_buffer(fptr) != 0) { if (!rb_io_wait_writable(fptr->fd)) return -1; rb_io_check_closed(fptr); } return 0; }
static int avi_write_ix(avi_Context* AVI) { char tag[5]; char ix_tag[] = "ix00"; int i, j; avi_RIFF *riff = avi_get_last_riff(AVI); if (riff->id > AVI_MASTER_INDEX_SIZE) return -1; for (i=0;i<AVI->stream_list_size;i++) { io_Stream *stream = get_stream(AVI->stream_list, i); int64_t ix, pos; avi_stream2fourcc(tag, stream); ix_tag[3] = '0' + i; /*only 10 streams supported*/ /* Writing AVI OpenDML leaf index chunk */ ix = io_get_offset(AVI->writer); io_write_4cc(AVI->writer, ix_tag); /* ix?? */ avi_Index* indexes = (avi_Index *) stream->indexes; io_write_wl32(AVI->writer, indexes->entry * 8 + 24); /* chunk size */ io_write_wl16(AVI->writer, 2); /* wLongsPerEntry */ io_write_w8(AVI->writer, 0); /* bIndexSubType (0 == frame index) */ io_write_w8(AVI->writer, AVI_INDEX_OF_CHUNKS); /* bIndexType (1 == AVI_INDEX_OF_CHUNKS) */ io_write_wl32(AVI->writer, indexes->entry); /* nEntriesInUse */ io_write_4cc(AVI->writer, tag); /* dwChunkId */ io_write_wl64(AVI->writer, riff->movi_list);/* qwBaseOffset */ io_write_wl32(AVI->writer, 0); /* dwReserved_3 (must be 0) */ for (j=0; j< indexes->entry; j++) { avi_Ientry* ie = avi_get_ientry(indexes, j); io_write_wl32(AVI->writer, ie->pos + 8); io_write_wl32(AVI->writer, ((uint32_t)ie->len & ~0x80000000) | (ie->flags & 0x10 ? 0 : 0x80000000)); } io_flush_buffer(AVI->writer); pos = io_get_offset(AVI->writer); //current position fprintf(stderr,"AVI: wrote ix %s with %i entries\n",tag, indexes->entry); /* Updating one entry in the AVI OpenDML master index */ io_seek(AVI->writer, indexes->indx_start); io_write_4cc(AVI->writer, "indx"); /* enabling this entry */ io_skip(AVI->writer, 8); io_write_wl32(AVI->writer, riff->id); /* nEntriesInUse */ io_skip(AVI->writer, 16*(riff->id)); io_write_wl64(AVI->writer, ix); /* qwOffset */ io_write_wl32(AVI->writer, pos - ix); /* dwSize */ io_write_wl32(AVI->writer, indexes->entry); /* dwDuration */ //return to position io_seek(AVI->writer, pos); } return 0; }
int avi_write_packet(avi_Context* AVI, int stream_index, BYTE *data, uint32_t size, int64_t dts, int block_align, int32_t flags) { char tag[5]; unsigned int i_flags=0; io_Stream *stream= get_stream(AVI->stream_list, stream_index); avi_RIFF* riff = avi_get_last_riff(AVI); //align while(block_align==0 && dts != AV_NOPTS_VALUE && dts > stream->packet_count) avi_write_packet(AVI, stream_index, NULL, 0, AV_NOPTS_VALUE, 0, 0); stream->packet_count++; // Make sure to put an OpenDML chunk when the file size exceeds the limits if (io_get_offset(AVI->writer) - riff->riff_start > AVI_MAX_RIFF_SIZE) { avi_write_ix(AVI); avi_close_tag(AVI, riff->movi_list); if (riff->id == 1) avi_write_idx1(AVI, riff); avi_close_tag(AVI, riff->riff_start); avi_add_new_riff(AVI); riff = avi_get_last_riff(AVI); //update riff } avi_stream2fourcc(tag, stream); if(flags & AV_PKT_FLAG_KEY) //key frame i_flags = 0x10; if (stream->type == STREAM_TYPE_AUDIO) stream->audio_strm_length += size; avi_Index* idx = (avi_Index*) stream->indexes; int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; if (idx->ents_allocated <= idx->entry) { idx->cluster = av_realloc(idx->cluster, (cl+1)*sizeof(void*)); if (!idx->cluster) return -1; idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(avi_Ientry)); if (!idx->cluster[cl]) return -1; idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = i_flags; idx->cluster[cl][id].pos = io_get_offset(AVI->writer) - riff->movi_list; idx->cluster[cl][id].len = size; idx->entry++; io_write_4cc(AVI->writer, tag); io_write_wl32(AVI->writer, size); io_write_buf(AVI->writer, data, size); if (size & 1) io_write_w8(AVI->writer, 0); io_flush_buffer(AVI->writer); return 0; }
static int avi_write_counters(avi_Context* AVI, avi_RIFF* riff) { int n, nb_frames = 0; io_flush_buffer(AVI->writer); //int time_base_num = AVI->time_base_num; //int time_base_den = AVI->time_base_den; int64_t file_size = io_get_offset(AVI->writer);//avi_tell(AVI); fprintf(stderr, "AVI: file size = %" PRIu64 "\n", file_size); for(n = 0; n < AVI->stream_list_size; n++) { io_Stream *stream = get_stream(AVI->stream_list, n); if(stream->rate_hdr_strm <= 0) { fprintf(stderr, "AVI: stream rate header pos not valid\n"); } else { io_seek(AVI->writer, stream->rate_hdr_strm); if(stream->type == STREAM_TYPE_VIDEO && AVI->fps > 0.001) { uint32_t rate =(uint32_t) FRAME_RATE_SCALE * lrintf(AVI->fps); fprintf(stderr,"AVI: storing rate(%i)\n",rate); io_write_wl32(AVI->writer, rate); } } if(stream->frames_hdr_strm <= 0) { fprintf(stderr, "AVI: stream frames header pos not valid\n"); } else { io_seek(AVI->writer, stream->frames_hdr_strm); if(stream->type == STREAM_TYPE_VIDEO) { io_write_wl32(AVI->writer, stream->packet_count); nb_frames = MAX(nb_frames, stream->packet_count); } else { int sampsize = avi_audio_sample_size(stream); io_write_wl32(AVI->writer, 4*stream->audio_strm_length/sampsize); } } } avi_RIFF* riff_1 = avi_get_riff(AVI, 1); if(riff_1->id == 1) /*should always be true*/ { if(riff_1->time_delay_off <= 0) { fprintf(stderr, "AVI: riff main header pos not valid\n"); } else { uint32_t us_per_frame = 1000; //us if(AVI->fps > 0.001) us_per_frame=(uint32_t) lrintf(1000000.0 / AVI->fps); AVI->avi_flags |= AVIF_HASINDEX; io_seek(AVI->writer, riff_1->time_delay_off); io_write_wl32(AVI->writer, us_per_frame); // time_per_frame io_write_wl32(AVI->writer, 0); // data rate io_write_wl32(AVI->writer, 0); // Padding multiple size (2048) io_write_wl32(AVI->writer, AVI->avi_flags); // parameter Flags //io_seek(AVI->writer, riff_1->frames_hdr_all); io_write_wl32(AVI->writer, nb_frames); } } //return to position (EOF) io_seek(AVI->writer, file_size); return 0; }