/* convert from unix to windows time */ static int64_t unix_to_file_time(int ti) { int64_t t; t = ti * int64_t_C(10000000); t += int64_t_C(116444736000000000); return t; }
int64_t av_gettime(void) { #ifdef CONFIG_WIN32 struct timeb tb; _ftime(&tb); return ((int64_t)tb.time * int64_t_C(1000) + (int64_t)tb.millitm) * int64_t_C(1000); #else struct timeval tv; gettimeofday(&tv,NULL); return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; #endif }
static int asf_write_packet(AVFormatContext *s, AVPacket *pkt) { ASFContext *asf = s->priv_data; ASFStream *stream; int64_t duration; AVCodecContext *codec; int64_t packet_st,pts; int start_sec,i; codec = s->streams[pkt->stream_index]->codec; stream = &asf->streams[pkt->stream_index]; //XXX /FIXME use duration from AVPacket (quick hack by) pts = (pkt->pts != AV_NOPTS_VALUE) ? pkt->pts : pkt->dts; if (pts == AV_NOPTS_VALUE) { if (codec->codec_type == CODEC_TYPE_AUDIO) { duration = (codec->frame_number * (int64_t)codec->frame_size * int64_t_C(10000000)) / codec->sample_rate; } else { duration = av_rescale(codec->frame_number * (int64_t)codec->time_base.num, 10000000, codec->time_base.den); } } else { duration = pts * 10000; } if (duration > asf->duration) asf->duration = duration; packet_st = asf->nb_packets; put_frame(s, stream, pkt->pts, pkt->data, pkt->size, pkt->flags); /* check index */ if ((!asf->is_streamed) && (codec->codec_type == CODEC_TYPE_VIDEO) && (pkt->flags & PKT_FLAG_KEY)) { start_sec = (int)(duration / int64_t_C(10000000)); if (start_sec != (int)(asf->last_indexed_pts / int64_t_C(10000000))) { for(i=asf->nb_index_count;i<start_sec;i++) { if (i>=asf->nb_index_memory_alloc) { asf->nb_index_memory_alloc += ASF_INDEX_BLOCK; asf->index_ptr = (ASFIndex*)av_realloc( asf->index_ptr, sizeof(ASFIndex) * asf->nb_index_memory_alloc ); } // store asf->index_ptr[i].packet_number = (uint32_t)packet_st; asf->index_ptr[i].packet_count = (uint16_t)(asf->nb_packets-packet_st); if (asf->maximum_packet < (uint16_t)(asf->nb_packets-packet_st)) asf->maximum_packet = (uint16_t)(asf->nb_packets-packet_st); } asf->nb_index_count = start_sec; asf->last_indexed_pts = duration; } } return 0; }
static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt) { VideoData *s = s1->priv_data; int64_t curtime, delay; struct timespec ts; /* Calculate the time of the next frame */ s->time_frame += int64_t_C(1000000); /* wait based on the frame rate */ for(;;) { curtime = av_gettime(); delay = s->time_frame * s->frame_rate_base / s->frame_rate - curtime; if (delay <= 0) { if (delay < int64_t_C(-1000000) * s->frame_rate_base / s->frame_rate) { /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */ s->time_frame += int64_t_C(1000000); } break; } ts.tv_sec = delay / 1000000; ts.tv_nsec = (delay % 1000000) * 1000; nanosleep(&ts, NULL); } if (av_new_packet(pkt, s->frame_size) < 0) return AVERROR_IO; pkt->pts = curtime; /* read one frame */ if (s->aiw_enabled) { return aiw_read_picture(s, pkt->data); } else if (s->use_mmap) { return v4l_mm_read_picture(s, pkt->data); } else { if (read(s->fd, pkt->data, pkt->size) != pkt->size) return AVERROR_IO; return s->frame_size; } }
static int avi_write_header(AVFormatContext *s) { AVIContext *avi = s->priv_data; ByteIOContext *pb = &s->pb; int bitrate, n, i, nb_frames, au_byterate, au_ssize, au_scale; AVCodecContext *stream, *video_enc; offset_t list1, list2, strh, strf; /* header list */ avi->riff_id = 0; list1 = avi_start_new_riff(avi, pb, "AVI ", "hdrl"); /* avi header */ put_tag(pb, "avih"); put_le32(pb, 14 * 4); bitrate = 0; video_enc = NULL; for(n=0;n<s->nb_streams;n++) { stream = &s->streams[n]->codec; bitrate += stream->bit_rate; if (stream->codec_type == CODEC_TYPE_VIDEO) video_enc = stream; } nb_frames = 0; if(video_enc){ put_le32(pb, (uint32_t)(int64_t_C(1000000) * video_enc->frame_rate_base / video_enc->frame_rate)); } else { put_le32(pb, 0); } put_le32(pb, bitrate / 8); /* XXX: not quite exact */ put_le32(pb, 0); /* padding */ put_le32(pb, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED); /* flags */ avi->frames_hdr_all = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, nb_frames); /* nb frames, filled later */ put_le32(pb, 0); /* initial frame */ put_le32(pb, s->nb_streams); /* nb streams */ put_le32(pb, 1024 * 1024); /* suggested buffer size */ if(video_enc){ put_le32(pb, video_enc->width); put_le32(pb, video_enc->height); } else { put_le32(pb, 0); put_le32(pb, 0); } put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ put_le32(pb, 0); /* reserved */ /* stream list */ for(i=0;i<n;i++) { list2 = start_tag(pb, "LIST"); put_tag(pb, "strl"); stream = &s->streams[i]->codec; /* FourCC should really be set by the codec itself */ if (! stream->codec_tag) { stream->codec_tag = codec_get_bmp_tag(stream->codec_id); } /* stream generic header */ strh = start_tag(pb, "strh"); switch(stream->codec_type) { case CODEC_TYPE_VIDEO: put_tag(pb, "vids"); put_le32(pb, stream->codec_tag); put_le32(pb, 0); /* flags */ put_le16(pb, 0); /* priority */ put_le16(pb, 0); /* language */ put_le32(pb, 0); /* initial frame */ put_le32(pb, stream->frame_rate_base); /* scale */ put_le32(pb, stream->frame_rate); /* rate */ av_set_pts_info(s->streams[i], 64, stream->frame_rate_base, stream->frame_rate); put_le32(pb, 0); /* start */ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, nb_frames); /* length, XXX: fill later */ put_le32(pb, 1024 * 1024); /* suggested buffer size */ put_le32(pb, -1); /* quality */ put_le32(pb, stream->width * stream->height * 3); /* sample size */ put_le16(pb, 0); put_le16(pb, 0); put_le16(pb, stream->width); put_le16(pb, stream->height); break; case CODEC_TYPE_AUDIO: put_tag(pb, "auds"); put_le32(pb, 1); /* tag */ put_le32(pb, 0); /* flags */ put_le16(pb, 0); /* priority */ put_le16(pb, 0); /* language */ put_le32(pb, 0); /* initial frame */ parse_specific_params(stream, &au_byterate, &au_ssize, &au_scale); put_le32(pb, au_scale); /* scale */ put_le32(pb, au_byterate); /* rate */ // av_set_pts_info(&s->streams[i], 64, au_scale, au_byterate); put_le32(pb, 0); /* start */ avi->frames_hdr_strm[i] = url_ftell(pb); /* remember this offset to fill later */ put_le32(pb, 0); /* length, XXX: filled later */ put_le32(pb, 12 * 1024); /* suggested buffer size */ put_le32(pb, -1); /* quality */ put_le32(pb, au_ssize); /* sample size */ put_le32(pb, 0); put_le32(pb, 0); break; default: av_abort(); } end_tag(pb, strh); strf = start_tag(pb, "strf"); switch(stream->codec_type) { case CODEC_TYPE_VIDEO: put_bmp_header(pb, stream, codec_bmp_tags, 0); break; case CODEC_TYPE_AUDIO: if (put_wav_header(pb, stream) < 0) { av_free(avi); return -1; } break; default: av_abort(); } end_tag(pb, strf); if (!url_is_streamed(pb)) { unsigned char tag[5]; int j; /* Starting to lay out AVI OpenDML master index. * We want to make it JUNK entry for now, since we'd * like to get away without making AVI an OpenDML one * for compatibility reasons. */ avi->indexes[i].entry = avi->indexes[i].ents_allocated = 0; avi->indexes[i].indx_start = start_tag(pb, "JUNK"); put_le16(pb, 4); /* wLongsPerEntry */ put_byte(pb, 0); /* bIndexSubType (0 == frame index) */ put_byte(pb, 0); /* bIndexType (0 == AVI_INDEX_OF_INDEXES) */ put_le32(pb, 0); /* nEntriesInUse (will fill out later on) */ put_tag(pb, avi_stream2fourcc(&tag[0], i, stream->codec_type)); /* dwChunkId */ put_le64(pb, 0); /* dwReserved[3] put_le32(pb, 0); Must be 0. */ for (j=0; j < AVI_MASTER_INDEX_SIZE * 2; j++) put_le64(pb, 0); end_tag(pb, avi->indexes[i].indx_start); } end_tag(pb, list2); } if (!url_is_streamed(pb)) { /* AVI could become an OpenDML one, if it grows beyond 2Gb range */ avi->odml_list = start_tag(pb, "JUNK"); put_tag(pb, "odml"); put_tag(pb, "dmlh"); put_le32(pb, 248); for (i = 0; i < 248; i+= 4) put_le32(pb, 0); end_tag(pb, avi->odml_list); } end_tag(pb, list1); avi->movi_list = start_tag(pb, "LIST"); put_tag(pb, "movi"); put_flush_packet(pb); return 0; }