static int write_video_data(struct ALL_DATA *all_data, BYTE *buff, int size) { struct VideoFormatData *videoF = all_data->videoF; struct GLOBAL *global = all_data->global; int ret =0; __LOCK_MUTEX( __FMUTEX ); switch (global->VidFormat) { case AVI_FORMAT: if(size > 0) ret = avi_write_packet(videoF->avi, 0, buff, size, videoF->vdts, videoF->vblock_align, videoF->vflags); //ret = AVI_write_frame (videoF->AviOut, buff, size, videoF->keyframe); break; case WEBM_FORMAT: case MKV_FORMAT: if(size > 0) { ret = mkv_write_packet(videoF->mkv, 0, buff, size, videoF->vduration, videoF->vpts, videoF->vflags); //ret = write_video_packet (buff, size, global->fps, videoF); } break; default: break; } __UNLOCK_MUTEX( __FMUTEX ); return (ret); }
static int write_skip_frames(AVFormatContext *s, int stream_index, int64_t dts) { AVIStream *avist = s->streams[stream_index]->priv_data; AVCodecContext *enc = s->streams[stream_index]->codec; av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(dts), avist->packet_count, stream_index); while (enc->block_align == 0 && dts != AV_NOPTS_VALUE && dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count) { AVPacket empty_packet; if (dts - avist->packet_count > 60000) { av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", dts - avist->packet_count); return AVERROR(EINVAL); } av_init_packet(&empty_packet); empty_packet.size = 0; empty_packet.data = NULL; empty_packet.stream_index = stream_index; avi_write_packet(s, &empty_packet); av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(dts), avist->packet_count); } return 0; }
/* * mux a audio frame * args: * encoder_ctx - pointer to encoder context * * asserts: * encoder_ctx is not null; * * returns: error code */ int encoder_write_audio_data(encoder_context_t *encoder_ctx) { /*assertions*/ assert(encoder_ctx != NULL); encoder_audio_context_t *enc_audio_ctx = encoder_ctx->enc_audio_ctx; if(!enc_audio_ctx || encoder_ctx->audio_channels <= 0) return -1; if(verbosity > 3) printf("ENCODER: writing %i bytes of audio data\n", enc_audio_ctx->outbuf_coded_size); if(enc_audio_ctx->outbuf_coded_size <= 0) return -1; int ret =0; int block_align = 1; encoder_codec_data_t *audio_codec_data = (encoder_codec_data_t *) enc_audio_ctx->codec_data; if(audio_codec_data) block_align = audio_codec_data->codec_context->block_align; __LOCK_MUTEX( __PMUTEX ); switch (encoder_ctx->muxer_id) { case ENCODER_MUX_AVI: ret = avi_write_packet( avi_ctx, 1, enc_audio_ctx->outbuf, enc_audio_ctx->outbuf_coded_size, enc_audio_ctx->dts, block_align, enc_audio_ctx->flags); break; case ENCODER_MUX_MKV: case ENCODER_MUX_WEBM: ret = mkv_write_packet( mkv_ctx, 1, enc_audio_ctx->outbuf, enc_audio_ctx->outbuf_coded_size, enc_audio_ctx->duration, enc_audio_ctx->pts, enc_audio_ctx->flags); break; default: break; } __UNLOCK_MUTEX( __PMUTEX ); return (ret); }
/* * mux a video frame * args: * encoder_ctx - pointer to encoder context * * asserts: * encoder_ctx is not null; * * returns: error code */ int encoder_write_video_data(encoder_context_t *encoder_ctx) { /*assertions*/ assert(encoder_ctx); encoder_video_context_t *enc_video_ctx = encoder_ctx->enc_video_ctx; assert(enc_video_ctx); if(enc_video_ctx->outbuf_coded_size <= 0) return -1; enc_video_ctx->framecount++; int ret =0; int block_align = 1; encoder_codec_data_t *video_codec_data = (encoder_codec_data_t *) enc_video_ctx->codec_data; if(video_codec_data) block_align = video_codec_data->codec_context->block_align; __LOCK_MUTEX( __PMUTEX ); switch (encoder_ctx->muxer_id) { case ENCODER_MUX_AVI: ret = avi_write_packet( avi_ctx, 0, enc_video_ctx->outbuf, enc_video_ctx->outbuf_coded_size, enc_video_ctx->dts, block_align, enc_video_ctx->flags); break; case ENCODER_MUX_MKV: case ENCODER_MUX_WEBM: ret = mkv_write_packet( mkv_ctx, 0, enc_video_ctx->outbuf, enc_video_ctx->outbuf_coded_size, enc_video_ctx->duration, enc_video_ctx->pts, enc_video_ctx->flags); break; default: break; } __UNLOCK_MUTEX( __PMUTEX ); return (ret); }
static int sync_audio_frame(struct ALL_DATA *all_data, AudBuff *proc_buff) { struct paRecordData *pdata = all_data->pdata; struct GLOBAL *global = all_data->global; struct VideoFormatData *videoF = all_data->videoF; switch (global->VidFormat) { case AVI_FORMAT: /*first audio data - sync with video (audio stream capture can take */ /*a bit longer to start) */ /*no need of locking the audio mutex yet, since we are not reading from the buffer*/ if (!get_stream(videoF->avi->stream_list, 1)->audio_strm_length) { /*only 1 audio stream*/ /*time diff for audio-video*/ int synctime= (int) (pdata->delay + pdata->snd_begintime - pdata->ts_ref)/1000000; /*convert to miliseconds*/ if (global->debug) g_print("shift sound by %d ms\n", synctime); if(synctime>10 && synctime<2000) { /*only sync between 10ms and 2 seconds*/ if(global->Sound_Format == PA_FOURCC) { /*shift sound by synctime*/ UINT32 shiftFrames = abs(synctime * global->Sound_SampRate / 1000); UINT32 shiftSamples = shiftFrames * global->Sound_NumChan; if (global->debug) g_print("shift sound forward by %d samples\n", shiftSamples); short *EmptySamp; EmptySamp=g_new0(short, shiftSamples); avi_write_packet(videoF->avi, 1, (BYTE *) EmptySamp, shiftSamples*sizeof(short), 0, -1, 0); //AVI_write_audio(videoF->AviOut,(BYTE *) EmptySamp,shiftSamples*sizeof(short)); g_free(EmptySamp); } else { /*use lavc encoder*/ } }
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; unsigned char tag[5]; unsigned int flags=0; const int stream_index= pkt->stream_index; AVIStream *avist= s->streams[stream_index]->priv_data; AVCodecContext *enc= s->streams[stream_index]->codec; int size= pkt->size; av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index); while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count){ AVPacket empty_packet; if(pkt->dts - avist->packet_count > 60000){ av_log(s, AV_LOG_ERROR, "Too large number of skipped frames %"PRId64" > 60000\n", pkt->dts - avist->packet_count); return AVERROR(EINVAL); } av_init_packet(&empty_packet); empty_packet.size= 0; empty_packet.data= NULL; empty_packet.stream_index= stream_index; avi_write_packet(s, &empty_packet); av_dlog(s, "dup dts:%s packet_count:%d\n", av_ts2str(pkt->dts), avist->packet_count); } avist->packet_count++; // Make sure to put an OpenDML chunk when the file size exceeds the limits if (pb->seekable && (avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { avi_write_ix(s); ff_end_tag(pb, avi->movi_list); if (avi->riff_id == 1) avi_write_idx1(s); ff_end_tag(pb, avi->riff_start); avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi"); } avi_stream2fourcc(tag, stream_index, enc->codec_type); if(pkt->flags&AV_PKT_FLAG_KEY) flags = 0x10; if (enc->codec_type == AVMEDIA_TYPE_AUDIO) { avist->audio_strm_length += size; } if (s->pb->seekable) { AVIIndex* idx = &avist->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_f(idx->cluster, sizeof(void*), cl+1); if (!idx->cluster) { idx->ents_allocated = 0; idx->entry = 0; return AVERROR(ENOMEM); } idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE*sizeof(AVIIentry)); if (!idx->cluster[cl]) return AVERROR(ENOMEM); idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = flags; idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; idx->cluster[cl][id].len = size; idx->entry++; } avio_write(pb, tag, 4); avio_wl32(pb, size); avio_write(pb, pkt->data, size); if (size & 1) avio_w8(pb, 0); return 0; }
static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) { AVIContext *avi = s->priv_data; ByteIOContext *pb = &s->pb; unsigned char tag[5]; unsigned int flags=0; const int stream_index= pkt->stream_index; AVCodecContext *enc= s->streams[stream_index]->codec; int size= pkt->size; // av_log(s, AV_LOG_DEBUG, "%"PRId64" %d %d\n", pkt->dts, avi->packet_count[stream_index], stream_index); while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avi->packet_count[stream_index]){ AVPacket empty_packet; av_init_packet(&empty_packet); empty_packet.size= 0; empty_packet.data= NULL; empty_packet.stream_index= stream_index; avi_write_packet(s, &empty_packet); // av_log(s, AV_LOG_DEBUG, "dup %"PRId64" %d\n", pkt->dts, avi->packet_count[stream_index]); } avi->packet_count[stream_index]++; // Make sure to put an OpenDML chunk when the file size exceeds the limits if (!url_is_streamed(pb) && (url_ftell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { avi_write_ix(s); end_tag(pb, avi->movi_list); if (avi->riff_id == 1) avi_write_idx1(s); end_tag(pb, avi->riff_start); avi->movi_list = avi_start_new_riff(avi, pb, "AVIX", "movi"); } avi_stream2fourcc(&tag[0], stream_index, enc->codec_type); if(pkt->flags&PKT_FLAG_KEY) flags = 0x10; if (enc->codec_type == CODEC_TYPE_AUDIO) { avi->audio_strm_length[stream_index] += size; } if (!url_is_streamed(&s->pb)) { AVIIndex* idx = &avi->indexes[stream_index]; 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(AVIIentry)); if (!idx->cluster[cl]) return -1; idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = flags; idx->cluster[cl][id].pos = url_ftell(pb) - avi->movi_list; idx->cluster[cl][id].len = size; idx->entry++; } put_buffer(pb, tag, 4); put_le32(pb, size); put_buffer(pb, pkt->data, size); if (size & 1) put_byte(pb, 0); put_flush_packet(pb); 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_packet(AVFormatContext *s, AVPacket *pkt) { unsigned char tag[5]; unsigned int flags = 0; const int stream_index = pkt->stream_index; int size = pkt->size; AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; AVIStream *avist = s->streams[stream_index]->priv_data; AVCodecContext *enc = s->streams[stream_index]->codec; while (enc->block_align == 0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count) { AVPacket empty_packet; av_init_packet(&empty_packet); empty_packet.size = 0; empty_packet.data = NULL; empty_packet.stream_index = stream_index; avi_write_packet(s, &empty_packet); } avist->packet_count++; // Make sure to put an OpenDML chunk when the file size exceeds the limits if (pb->seekable && (avio_tell(pb) - avi->riff_start > AVI_MAX_RIFF_SIZE)) { avi_write_ix(s); ff_end_tag(pb, avi->movi_list); if (avi->riff_id == 1) avi_write_idx1(s); ff_end_tag(pb, avi->riff_start); avi->movi_list = avi_start_new_riff(s, pb, "AVIX", "movi"); } avi_stream2fourcc(tag, stream_index, enc->codec_type); if (pkt->flags & AV_PKT_FLAG_KEY) flags = 0x10; if (enc->codec_type == AVMEDIA_TYPE_AUDIO) avist->audio_strm_length += size; if (s->pb->seekable) { int err; AVIIndex *idx = &avist->indexes; int cl = idx->entry / AVI_INDEX_CLUSTER_SIZE; int id = idx->entry % AVI_INDEX_CLUSTER_SIZE; if (idx->ents_allocated <= idx->entry) { if ((err = av_reallocp(&idx->cluster, (cl + 1) * sizeof(*idx->cluster))) < 0) { idx->ents_allocated = 0; idx->entry = 0; return err; } idx->cluster[cl] = av_malloc(AVI_INDEX_CLUSTER_SIZE * sizeof(AVIIentry)); if (!idx->cluster[cl]) return -1; idx->ents_allocated += AVI_INDEX_CLUSTER_SIZE; } idx->cluster[cl][id].flags = flags; idx->cluster[cl][id].pos = avio_tell(pb) - avi->movi_list; idx->cluster[cl][id].len = size; idx->entry++; } avio_write(pb, tag, 4); avio_wl32(pb, size); avio_write(pb, pkt->data, size); if (size & 1) avio_w8(pb, 0); return 0; }