int main(int argc, char **argv) { OutputStream audio_st = { 0 }; const char *filename; AVOutputFormat *fmt; AVFormatContext *oc; AVCodec *audio_codec; int ret; int have_audio = 0; int encode_audio = 0; AVDictionary *opt = NULL; /* Initialize libavcodec, and register all codecs and formats. */ av_register_all(); avformat_network_init(); if (argc < 2) { printf("usage: %s output_file\n", argv[0]); return 1; } av_dict_set(&opt, "strict", "experimental", 0); filename = argv[1]; if (argc > 3 && !strcmp(argv[2], "-flags")) { av_dict_set(&opt, argv[2]+1, argv[3], 0); } /* allocate the output media context */ avformat_alloc_output_context2(&oc, NULL, "sdp", filename); if (!oc) { printf("Could not deduce output format from file extension: using MPEG.\n"); avformat_alloc_output_context2(&oc, NULL, "mpeg", filename); } if (!oc) return 1; fmt = oc->oformat; /* Add the audio and video streams using the default format codecs * and initialize the codecs. */ if (fmt->audio_codec != AV_CODEC_ID_NONE) { add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec); } /* Now that all the parameters are set, we can open the audio and * video codecs and allocate the necessary encode buffers. */ open_audio(oc, audio_codec, &audio_st, opt); av_dump_format(oc, 0, filename, 1); /* open the output file, if needed */ if (!(fmt->flags & AVFMT_NOFILE)) { ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, "Could not open '%s': %s\n", filename, av_err2str(ret)); return 1; } } /* Write the stream header, if any. */ ret = avformat_write_header(oc, &opt); if (ret < 0) { fprintf(stderr, "Error occurred when opening output file: %s\n", av_err2str(ret)); return 1; } while (encode_audio) { /* select the stream to encode */ encode_audio = !write_audio_frame(oc, &audio_st); } /* Write the trailer, if any. The trailer must be written before you * close the CodecContexts open when you wrote the header; otherwise * av_write_trailer() may try to use memory that was freed on * av_codec_close(). */ av_write_trailer(oc); /* Close each codec. */ close_stream(oc, &audio_st); if (!(fmt->flags & AVFMT_NOFILE)) /* Close the output file. */ avio_close(oc->pb); /* free the stream */ avformat_free_context(oc); return 0; }
/* media file output */ int main(int argc, char **argv) { const char *filename; AVOutputFormat *fmt; AVFormatContext *oc; AVStream *video_st = NULL; AVCodec *video_codec = NULL; double video_time; int flush, ret; /* Initialize libavcodec, and register all codecs and formats. */ av_register_all(); filename = "E:\\muxing.mp4"; /* allocate the output media context */ avformat_alloc_output_context2(&oc, NULL, NULL, filename); if (!oc) { printf("Could not deduce output format from file extension: using MPEG.\n"); avformat_alloc_output_context2(&oc, NULL, "mpeg", filename); } if (!oc) return 1; fmt = oc->oformat; //muxing 할 때 outputformat 설정 /* Add the audio and video streams using the default format codecs * and initialize the codecs. */ //fmt->video_codec = AV_CODEC_ID_H264; fmt->video_codec = AV_CODEC_ID_MPEG4; if (fmt->video_codec != AV_CODEC_ID_NONE) video_st = add_stream(oc, &video_codec, fmt->video_codec); // add_stream(AVFormatContext *oc, AVCodec **codec,enum AVCodecID codec_id) // codec parameters set 함수 /* Now that all the parameters are set, we can open the audio and * video codecs and allocate the necessary encode buffers. */ if (video_st) open_video(oc, video_codec, video_st); // (AVFormatContext *oc, AVCodec *codec, AVStream *st) // 코댁 열기, 프레임 설정 av_dump_format(oc, 0, filename, 1); // 정보 출력 디버깅 함수 /* open the output file, if needed */ if (!(fmt->flags & AVFMT_NOFILE)) { ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE); if (ret < 0) { char buf[256]; av_strerror(ret, buf, sizeof(buf)); fprintf(stderr, "Could not open '%s': %s\n", filename, buf); return 1; } } /* Write the stream header, if any. */ ret = avformat_write_header(oc, NULL); // Allocate the stream private data and write the stream header to an output media file. // 헤더파일 생성 -> 본체 생성 -> 마무리 작업 if (ret < 0) { char buf[256]; av_strerror(ret, buf, sizeof(buf)); fprintf(stderr, "Error occurred when opening output file: %s\n", buf); return 1; } flush = 0; while ((video_st && !video_is_eof)) { if (!flush && (!video_st)) { flush = 1; } if (video_st && !video_is_eof) { write_video_frame(oc, video_st, flush); // 본체 생성 } if (frame_count == 10000) break; } /* Write the trailer, if any. The trailer must be written before you * close the CodecContexts open when you wrote the header; otherwise * av_write_trailer() may try to use memory that was freed on * av_codec_close(). */ av_write_trailer(oc); /* Close each codec. */ if (video_st) close_video(oc, video_st); if (!(fmt->flags & AVFMT_NOFILE)) /* Close the output file. */ avio_close(oc->pb); /* free the stream */ avformat_free_context(oc); return 0; }
static int rtp_new_av_stream(RTSPContext *ctx, struct sockaddr_in *sin, int streamid, enum AVCodecID codecid) { AVOutputFormat *fmt = NULL; AVFormatContext *fmtctx = NULL; AVStream *stream = NULL; AVCodecContext *encoder = NULL; uint8_t *dummybuf = NULL; // if(streamid > VIDEO_SOURCE_CHANNEL_MAX) { ga_error("invalid stream index (%d > %d)\n", streamid, VIDEO_SOURCE_CHANNEL_MAX); return -1; } if(codecid != rtspconf->video_encoder_codec->id && codecid != rtspconf->audio_encoder_codec->id) { ga_error("invalid codec (%d)\n", codecid); return -1; } if(ctx->fmtctx[streamid] != NULL) { ga_error("duplicated setup to an existing stream (%d)\n", streamid); return -1; } if((fmt = av_guess_format("rtp", NULL, NULL)) == NULL) { ga_error("RTP not supported.\n"); return -1; } if((fmtctx = avformat_alloc_context()) == NULL) { ga_error("create avformat context failed.\n"); return -1; } fmtctx->oformat = fmt; if(ctx->mtu > 0) { if(fmtctx->packet_size > 0) { fmtctx->packet_size = ctx->mtu < fmtctx->packet_size ? ctx->mtu : fmtctx->packet_size; } else { fmtctx->packet_size = ctx->mtu; } ga_error("RTP: packet size set to %d (configured: %d)\n", fmtctx->packet_size, ctx->mtu); } #ifdef HOLE_PUNCHING if(ffio_open_dyn_packet_buf(&fmtctx->pb, ctx->mtu) < 0) { ga_error("cannot open dynamic packet buffer\n"); return -1; } ga_error("RTP: Dynamic buffer opened, max_packet_size=%d.\n", (int) fmtctx->pb->max_packet_size); if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_UDP) { if(rtp_open_ports(ctx, streamid) < 0) { ga_error("RTP: open ports failed - %s\n", strerror(errno)); return -1; } } #else if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_UDP) { snprintf(fmtctx->filename, sizeof(fmtctx->filename), "rtp://%s:%d", inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); if(avio_open(&fmtctx->pb, fmtctx->filename, AVIO_FLAG_WRITE) < 0) { ga_error("cannot open URL: %s\n", fmtctx->filename); return -1; } ga_error("RTP/UDP: URL opened [%d]: %s, max_packet_size=%d\n", streamid, fmtctx->filename, fmtctx->pb->max_packet_size); } else if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_TCP) { // XXX: should we use avio_open_dyn_buf(&fmtctx->pb)? if(ffio_open_dyn_packet_buf(&fmtctx->pb, ctx->mtu) < 0) { ga_error("cannot open dynamic packet buffer\n"); return -1; } ga_error("RTP/TCP: Dynamic buffer opened, max_packet_size=%d.\n", (int) fmtctx->pb->max_packet_size); } #endif fmtctx->pb->seekable = 0; // if((stream = ga_avformat_new_stream(fmtctx, 0, codecid == rtspconf->video_encoder_codec->id ? rtspconf->video_encoder_codec : rtspconf->audio_encoder_codec)) == NULL) { ga_error("Cannot create new stream (%d)\n", codecid); return -1; } // if(codecid == rtspconf->video_encoder_codec->id) { encoder = ga_avcodec_vencoder_init( stream->codec, rtspconf->video_encoder_codec, video_source_out_width(streamid), video_source_out_height(streamid), rtspconf->video_fps, rtspconf->vso); } else if(codecid == rtspconf->audio_encoder_codec->id) { encoder = ga_avcodec_aencoder_init( stream->codec, rtspconf->audio_encoder_codec, rtspconf->audio_bitrate, rtspconf->audio_samplerate, rtspconf->audio_channels, rtspconf->audio_codec_format, rtspconf->audio_codec_channel_layout); } if(encoder == NULL) { ga_error("Cannot init encoder\n"); return -1; } // ctx->encoder[streamid] = encoder; ctx->stream[streamid] = stream; ctx->fmtctx[streamid] = fmtctx; // write header if(avformat_write_header(ctx->fmtctx[streamid], NULL) < 0) { ga_error("Cannot write stream id %d.\n", streamid); return -1; } #ifdef HOLE_PUNCHING avio_close_dyn_buf(ctx->fmtctx[streamid]->pb, &dummybuf); av_free(dummybuf); #else if(ctx->lower_transport[streamid] == RTSP_LOWER_TRANSPORT_TCP) { /*int rlen; rlen =*/ avio_close_dyn_buf(ctx->fmtctx[streamid]->pb, &dummybuf); av_free(dummybuf); } #endif return 0; }
static bool ffemu_init_muxer(ffemu_t *handle) { AVFormatContext *ctx = avformat_alloc_context(); av_strlcpy(ctx->filename, handle->params.filename, sizeof(ctx->filename)); ctx->oformat = av_guess_format(NULL, ctx->filename, NULL); if (!ctx->oformat) return false; // FFmpeg sure likes to make things difficult. #if defined(AVIO_FLAG_WRITE) #define FFMPEG_FLAG_RW AVIO_FLAG_WRITE #elif defined(AVIO_WRONLY) #define FFMPEG_FLAG_RW AVIO_WRONLY #elif defined(URL_WRONLY) #define FFMPEG_FLAG_RW URL_WRONLY #else #define FFMPEG_FLAG_RW 2 // Seems to be consistent, but you never know. #endif #ifdef HAVE_FFMPEG_AVIO_OPEN if (avio_open(&ctx->pb, ctx->filename, FFMPEG_FLAG_RW) < 0) #else if (url_fopen(&ctx->pb, ctx->filename, FFMPEG_FLAG_RW) < 0) #endif { av_free(ctx); return false; } #ifdef HAVE_FFMPEG_AVFORMAT_NEW_STREAM AVStream *stream = avformat_new_stream(ctx, handle->video.encoder); #else unsigned stream_cnt = 0; AVStream *stream = av_new_stream(ctx, stream_cnt++); #endif stream->codec = handle->video.codec; if (ctx->oformat->flags & AVFMT_GLOBALHEADER) handle->video.codec->flags |= CODEC_FLAG_GLOBAL_HEADER; handle->muxer.vstream = stream; handle->muxer.vstream->sample_aspect_ratio = handle->video.codec->sample_aspect_ratio; #ifdef HAVE_FFMPEG_AVFORMAT_NEW_STREAM stream = avformat_new_stream(ctx, handle->audio.encoder); #else stream = av_new_stream(ctx, stream_cnt++); #endif stream->codec = handle->audio.codec; if (ctx->oformat->flags & AVFMT_GLOBALHEADER) handle->audio.codec->flags |= CODEC_FLAG_GLOBAL_HEADER; handle->muxer.astream = stream; #ifdef AVFMT_TS_NONSTRICT // Avoids a warning at end about non-monotonically increasing DTS values. // It seems to be harmless to disable this. if (g_settings.video.h264_record) ctx->oformat->flags |= AVFMT_TS_NONSTRICT; #endif av_dict_set(&ctx->metadata, "title", "RetroArch video dump", 0); #ifdef HAVE_FFMPEG_AVFORMAT_WRITE_HEADER if (avformat_write_header(ctx, NULL) < 0) #else if (av_write_header(ctx) != 0) #endif return false; handle->muxer.ctx = ctx; return true; }
MediaRecorder::MediaRecorder(const char * outfile,int width, int height) { audiofailed = false; /* INIT SOUND RECORDING */ debug_samples_out = fopen("audiosamples.s16","wb"); audio_samples_written = 0; pa_context* pactx; pa_mainloop * m = pa_mainloop_new(); m_api = pa_mainloop_get_api(m); pactx = pa_context_new(m_api,"Rec1"); if ( pa_context_connect(pactx,NULL,(pa_context_flags_t)0,NULL) < 0 ) printf("Cannot connect to pulseaudio\n"); int ret; pa_context_set_state_callback(pactx, context_state_callback, this); pa_mainloop_run(m,&ret); std::cout << "Use source: " << monitorsources[defaultsink] << std::endl; static const pa_sample_spec ss = { .format = PA_SAMPLE_S16LE, .rate = 44100, .channels = 2 }; pa_context_disconnect(pactx); int error; s = pa_simple_new(NULL,"GLCAP Record",PA_STREAM_RECORD,monitorsources[defaultsink].c_str(), "record", &ss, NULL,NULL , &error); if ( !s ) { printf("Cannot create pa_simple\n"); } run = true; ready = false; firstframe = true; this->width = width; this->height = height; pthread_mutex_init(&encode_mutex,NULL); pthread_mutex_init(&sound_buffer_lock,NULL); pthread_cond_init(&encode_cond,NULL); pthread_create(&encode_thread,NULL,(void*(*)(void*))&MediaRecorder::EncodingThread,this); av_log_set_level(AV_LOG_DEBUG); outCtx = avformat_alloc_context(); outCtx->oformat = av_guess_format(NULL, outfile, NULL); snprintf(outCtx->filename, sizeof(outCtx->filename), "%s", outfile); codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4); acodec = avcodec_find_encoder(AV_CODEC_ID_MP2); ctx = avcodec_alloc_context3(codec); actx = avcodec_alloc_context3(acodec); avcodec_get_context_defaults3(actx,acodec); avcodec_get_context_defaults3(ctx,codec); ctx->width = width; ctx->height = height; ctx->bit_rate = 6000*1000; std::cout << ctx->time_base.den << " " << ctx->time_base.num << std::endl; ctx->time_base.den = TIMEBASE; ctx->time_base.num = 1; ctx->thread_count = 4; ctx->qmin = 2; ctx->qmax = 31; ctx->b_sensitivity = 100; ctx->gop_size = 1; ctx->me_method = 1; ctx->global_quality = 100; ctx->lowres = 0; ctx->bit_rate_tolerance = 200000; actx->sample_fmt = AV_SAMPLE_FMT_S16; actx->sample_rate = 44100; actx->channels = 2; actx->time_base.den = 44100; actx->time_base.num = 1; actx->bit_rate = 128000; actx->frame_size = 8192; actx->channel_layout = 3; /* ctx->compression_level = 0; ctx->trellis = 0; ctx->gop_size = 1; /* emit one intra frame every ten frames */ /*ctx->me_pre_cmp = 0; ctx->me_cmp = 0; ctx->me_sub_cmp = 0; ctx->mb_cmp = 2; ctx->pre_dia_size = 0; ctx->dia_size = 1; ctx->quantizer_noise_shaping = 0; // qns=0 ctx->noise_reduction = 0; // nr=0 ctx->mb_decision = 0; // mbd=0 ("realtime" encoding) ctx->flags &= ~CODEC_FLAG_QPEL; ctx->flags &= ~CODEC_FLAG_4MV; ctx->trellis = 0; ctx->flags &= ~CODEC_FLAG_CBP_RD; ctx->flags &= ~CODEC_FLAG_QP_RD; ctx->flags &= ~CODEC_FLAG_MV0;*/ //ctx->s ctx->pix_fmt = PIX_FMT_YUV420P; if (avcodec_open2(ctx, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); } if (avcodec_open2(actx, acodec, NULL) < 0) { fprintf(stderr, "Could not open audio codec\n"); audiofailed = true; } printf("frame_size: %d\n",actx->frame_size); pthread_create(&record_sound_thread,NULL,(void*(*)(void*))&MediaRecorder::RecordingThread,this); AVStream* s = av_new_stream(outCtx,0); s->codec = ctx; s->r_frame_rate.den = TIMEBASE; s->r_frame_rate.num = 1; if (!audiofailed ) { AVStream* as = av_new_stream(outCtx,1); as->codec = actx; as->r_frame_rate.den = 44100; as->r_frame_rate.num = 1; } picture = alloc_picture(PIX_FMT_YUV420P, ctx->width, ctx->height); if (!picture) { fprintf(stderr, "Could not allocate picture\n"); exit(1); } tmp_picture = NULL; tmp_picture = alloc_picture(PIX_FMT_RGBA, ctx->width, ctx->height); if (!tmp_picture) { fprintf(stderr, "Could not allocate temporary picture\n"); exit(1); } img_convert_ctx = sws_getContext(ctx->width, ctx->height, PIX_FMT_RGBA, ctx->width, ctx->height, PIX_FMT_YUV420P, SWS_FAST_BILINEAR , NULL, NULL, NULL); if (img_convert_ctx == NULL) { fprintf(stderr, "Cannot initialize the conversion context\n"); exit(1); } av_dump_format(outCtx, 0, outfile, 1); avio_open2(&outCtx->pb, outfile, AVIO_FLAG_WRITE,NULL,NULL); avformat_write_header(outCtx,NULL); } MediaRecorder::~MediaRecorder() { run = false; ready = false; pthread_cond_broadcast(&encode_cond); printf("Joining thread..\n"); pthread_join(encode_thread,NULL); printf("Joining recording thread..\n"); pthread_join(record_sound_thread,NULL); printf("Done\n"); av_write_trailer(outCtx); av_free(picture); avformat_free_context(outCtx); pa_simple_free(s); fclose(debug_samples_out); } int fcount = 0; void MediaRecorder::AppendFrame(float time, int width, int height, char* data) { if ( !ready ) return ; printf("AppendFrame\n"); this->time = getcurrenttime2(); if ( firstframe ) { starttime = getcurrenttime2(); firstframe = false; } this->height = height; this->width = width; m_data = data; ready = false; pthread_cond_broadcast(&encode_cond); /*int i = 0; unsigned int numpixels = width * height; unsigned int ui = numpixels; unsigned int vi = numpixels + numpixels / 4; for ( int j = 0; j < height; j++ ) { for ( int k = 0; k < width; k++ ) { int sR = data[i*4+0]; int sG = data[i*4+1]; int sB = data[i*4+2]; picture->data[0][i] = ( (66*sR + 129*sG + 25*sB + 128) >> 8) + 16; if (0 == j%2 && 0 == k%2) { picture->data[0][ui++] = ( (-38*sR - 74*sG + 112*sB + 128) >> 8) + 128; picture->data[0][vi++] = ( (112*sR - 94*sG - 18*sB + 128) >> 8) + 128; } i++; } }*/ // printf("End flip %f\n",(float)getcurrenttime2()); //memcpy(tmp_picture->data[0],data,width*height*4); } void MediaRecorder::EncodingThread() { while ( run ) { printf("Encode thread ready\n"); ready = true; pthread_cond_wait(&encode_cond,&encode_mutex); if (!run) { printf("Encoding finished\n"); break; } for ( int y = 0; y < height; y++ ) { /*for ( int x = 0; x < width; x++ ) {*/ char r,g,b; int oldindex = (y*width); int newindex = ((height-1-y)*width); memcpy(&tmp_picture->data[0][(newindex)*4],&m_data[oldindex*4],width*4); /* r = data[oldindex*4+0]; g = data[oldindex*4+1]; b = data[oldindex*4+2]; tmp_picture->data[0][(newindex)*4+0] = r; tmp_picture->data[0][(newindex)*4+1] = g; tmp_picture->data[0][(newindex)*4+2] = b; */ // } } sws_scale(img_convert_ctx,tmp_picture->data,tmp_picture->linesize,0,height,picture->data,picture->linesize); AVPacket p; av_init_packet(&p); p.data = NULL; p.size = 0; picture->pts = int64_t((time-starttime)*TIMEBASE); uint64_t vpts = picture->pts; // picture->pts = time*30.0; int got_frame; printf("%p %p\n",ctx, picture); if(avcodec_encode_video2(ctx, &p, picture, &got_frame) < 0) return; if(got_frame) { // outContainer is "mp4" p.pts = vpts; p.dts = AV_NOPTS_VALUE; av_write_frame(outCtx, &p); av_free_packet(&p); } //sleep(1); printf("End enc frame %f, pts %lld\n",(float)getcurrenttime2(),picture->pts); AVFrame * aframe = avcodec_alloc_frame(); bool unlocked = false; while ( sound_buffers.size() > 0 ) { uint64_t apts = audio_samples_written; /* if ( apts > vpts ) break;*/ pthread_mutex_lock(&sound_buffer_lock); short * buf = sound_buffers.front(); sound_buffers.pop_front(); pthread_mutex_unlock(&sound_buffer_lock); if (!audiofailed ) { unlocked = true; aframe->nb_samples = actx->frame_size; aframe->channel_layout = actx->channel_layout; aframe->format = AV_SAMPLE_FMT_S16; aframe->channels = actx->channels; avcodec_fill_audio_frame(aframe,actx->channels,AV_SAMPLE_FMT_S16,(char*)buf,actx->frame_size*2*2,0); // avcodec_fill_audio_frame(aframe,actx->channels,actx->sample_fmt,(char*)buf,actx->frame_size*2,0); printf("sound_buffers.size() = %d\n",sound_buffers.size()); av_init_packet(&p); p.data = NULL; p.size = 0; avcodec_encode_audio2(actx,&p,aframe,&got_frame); if ( got_frame ) { p.stream_index = 1; p.flags |= AV_PKT_FLAG_KEY; av_write_frame(outCtx,&p); av_free_packet(&p); } audio_samples_written += actx->frame_size;//samples/2 each channel } //printf("Consumed 1024 samples\n"); delete[] buf; } /* if ( !unlocked ) pthread_mutex_unlock(&sound_buffer_lock);*/ avcodec_free_frame(&aframe); } } bool MediaRecorder::isReady() { return ready; }
bool AVIDump::CreateFile() { AVCodec* codec = nullptr; s_format_context = avformat_alloc_context(); std::stringstream s_file_index_str; s_file_index_str << s_file_index; snprintf(s_format_context->filename, sizeof(s_format_context->filename), "%s", (File::GetUserPath(D_DUMPFRAMES_IDX) + "framedump" + s_file_index_str.str() + ".avi") .c_str()); File::CreateFullPath(s_format_context->filename); // Ask to delete file if (File::Exists(s_format_context->filename)) { if (SConfig::GetInstance().m_DumpFramesSilent || AskYesNoT("Delete the existing file '%s'?", s_format_context->filename)) { File::Delete(s_format_context->filename); } else { // Stop and cancel dumping the video return false; } } if (!(s_format_context->oformat = av_guess_format("avi", nullptr, nullptr)) || !(s_stream = avformat_new_stream(s_format_context, codec))) { return false; } s_stream->codec->codec_id = g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 : s_format_context->oformat->video_codec; if (!g_Config.bUseFFV1) s_stream->codec->codec_tag = MKTAG('X', 'V', 'I', 'D'); // Force XVID FourCC for better compatibility s_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; s_stream->codec->bit_rate = 400000; s_stream->codec->width = s_width; s_stream->codec->height = s_height; s_stream->codec->time_base.num = 1; s_stream->codec->time_base.den = VideoInterface::GetTargetRefreshRate(); s_stream->codec->gop_size = 12; s_stream->codec->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA : AV_PIX_FMT_YUV420P; if (!(codec = avcodec_find_encoder(s_stream->codec->codec_id)) || (avcodec_open2(s_stream->codec, codec, nullptr) < 0)) { return false; } s_src_frame = av_frame_alloc(); s_scaled_frame = av_frame_alloc(); s_scaled_frame->format = s_stream->codec->pix_fmt; s_scaled_frame->width = s_width; s_scaled_frame->height = s_height; #if LIBAVCODEC_VERSION_MAJOR >= 55 if (av_frame_get_buffer(s_scaled_frame, 1)) return false; #else if (avcodec_default_get_buffer(s_stream->codec, s_scaled_frame)) return false; #endif NOTICE_LOG(VIDEO, "Opening file %s for dumping", s_format_context->filename); if (avio_open(&s_format_context->pb, s_format_context->filename, AVIO_FLAG_WRITE) < 0 || avformat_write_header(s_format_context, nullptr)) { WARN_LOG(VIDEO, "Could not open %s", s_format_context->filename); return false; } OSD::AddMessage(StringFromFormat("Dumping Frames to \"%s\" (%dx%d)", s_format_context->filename, s_width, s_height)); return true; }
int main(int argc, char *argv[]) { IDeckLinkIterator *deckLinkIterator = CreateDeckLinkIteratorInstance(); DeckLinkCaptureDelegate *delegate; BMDDisplayMode selectedDisplayMode = bmdModeNTSC; int displayModeCount = 0; int exitStatus = 1; int aconnection = 0, vconnection = 0, camera = 0, i = 0; int ch; AVDictionary *opts = NULL; BMDPixelFormat pix = bmdFormat8BitYUV; HRESULT result; pthread_t th; pthread_mutex_init(&sleepMutex, NULL); pthread_cond_init(&sleepCond, NULL); av_register_all(); if (!deckLinkIterator) { fprintf(stderr, "This application requires the DeckLink drivers installed.\n"); goto bail; } // Parse command line options while ((ch = getopt(argc, argv, "?hvc:s:f:a:m:n:p:M:F:C:A:V:o:")) != -1) { switch (ch) { case 'v': g_verbose = true; break; case 'm': g_videoModeIndex = atoi(optarg); break; case 'c': g_audioChannels = atoi(optarg); if (g_audioChannels != 2 && g_audioChannels != 8 && g_audioChannels != 16) { fprintf( stderr, "Invalid argument: Audio Channels must be either 2, 8 or 16\n"); goto bail; } break; case 's': g_audioSampleDepth = atoi(optarg); switch (g_audioSampleDepth) { case 16: sample_fmt = AV_SAMPLE_FMT_S16; break; case 32: sample_fmt = AV_SAMPLE_FMT_S32; break; default: fprintf(stderr, "Invalid argument:" " Audio Sample Depth must be either 16 bits" " or 32 bits\n"); goto bail; } break; case 'p': switch (atoi(optarg)) { case 8: pix = bmdFormat8BitYUV; pix_fmt = PIX_FMT_UYVY422; break; case 10: pix = bmdFormat10BitYUV; pix_fmt = PIX_FMT_YUV422P10; break; default: fprintf( stderr, "Invalid argument: Pixel Format Depth must be either 8 bits or 10 bits\n"); goto bail; } break; case 'f': g_videoOutputFile = optarg; break; case 'n': g_maxFrames = atoi(optarg); break; case 'M': g_memoryLimit = atoi(optarg) * 1024 * 1024 * 1024L; break; case 'F': fmt = av_guess_format(optarg, NULL, NULL); break; case 'A': aconnection = atoi(optarg); break; case 'V': vconnection = atoi(optarg); break; case 'C': camera = atoi(optarg); break; case 'S': serial_fd = open(optarg, O_RDWR | O_NONBLOCK); break; case 'o': if (av_dict_parse_string(&opts, optarg, "=", ":", 0) < 0) { fprintf(stderr, "Cannot parse option string %s\n", optarg); goto bail; } case '?': case 'h': usage(0); } } /* Connect to the first DeckLink instance */ do result = deckLinkIterator->Next(&deckLink); while (i++ < camera); if (result != S_OK) { fprintf(stderr, "No DeckLink PCI cards found.\n"); goto bail; } if (deckLink->QueryInterface(IID_IDeckLinkInput, (void **)&deckLinkInput) != S_OK) { goto bail; } result = deckLink->QueryInterface(IID_IDeckLinkConfiguration, (void **)&deckLinkConfiguration); if (result != S_OK) { fprintf( stderr, "Could not obtain the IDeckLinkConfiguration interface - result = %08x\n", result); goto bail; } result = S_OK; switch (aconnection) { case 1: result = DECKLINK_SET_AUDIO_CONNECTION(bmdAudioConnectionAnalog); break; case 2: result = DECKLINK_SET_AUDIO_CONNECTION(bmdAudioConnectionEmbedded); break; case 3: result = DECKLINK_SET_AUDIO_CONNECTION(bmdAudioConnectionAESEBU); break; default: // do not change it break; } if (result != S_OK) { fprintf(stderr, "Failed to set audio input - result = %08x\n", result); goto bail; } result = S_OK; switch (vconnection) { case 1: result = DECKLINK_SET_VIDEO_CONNECTION(bmdVideoConnectionComposite); break; case 2: result = DECKLINK_SET_VIDEO_CONNECTION(bmdVideoConnectionComponent); break; case 3: result = DECKLINK_SET_VIDEO_CONNECTION(bmdVideoConnectionHDMI); break; case 4: result = DECKLINK_SET_VIDEO_CONNECTION(bmdVideoConnectionSDI); break; case 5: result = DECKLINK_SET_VIDEO_CONNECTION(bmdVideoConnectionOpticalSDI); break; case 6: result = DECKLINK_SET_VIDEO_CONNECTION(bmdVideoConnectionSVideo); break; default: // do not change it break; } if (result != S_OK) { fprintf(stderr, "Failed to set video input - result %08x\n", result); goto bail; } delegate = new DeckLinkCaptureDelegate(); deckLinkInput->SetCallback(delegate); // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on output result = deckLinkInput->GetDisplayModeIterator(&displayModeIterator); if (result != S_OK) { fprintf( stderr, "Could not obtain the video output display mode iterator - result = %08x\n", result); goto bail; } if (!g_videoOutputFile) { fprintf(stderr, "Missing argument: Please specify output path using -f\n"); goto bail; } if (!fmt) { fmt = av_guess_format(NULL, g_videoOutputFile, NULL); if (!fmt) { fprintf( stderr, "Unable to guess output format, please specify explicitly using -F\n"); goto bail; } } if (g_videoModeIndex < 0) { fprintf(stderr, "No video mode specified\n"); usage(0); } selectedDisplayMode = -1; while (displayModeIterator->Next(&displayMode) == S_OK) { if (g_videoModeIndex == displayModeCount) { selectedDisplayMode = displayMode->GetDisplayMode(); break; } displayModeCount++; displayMode->Release(); } if (selectedDisplayMode < 0) { fprintf(stderr, "Invalid mode %d specified\n", g_videoModeIndex); goto bail; } result = deckLinkInput->EnableVideoInput(selectedDisplayMode, pix, 0); if (result != S_OK) { fprintf(stderr, "Failed to enable video input. Is another application using " "the card?\n"); goto bail; } result = deckLinkInput->EnableAudioInput(bmdAudioSampleRate48kHz, g_audioSampleDepth, g_audioChannels); if (result != S_OK) { fprintf(stderr, "Failed to enable audio input. Is another application using " "the card?\n"); goto bail; } oc = avformat_alloc_context(); oc->oformat = fmt; snprintf(oc->filename, sizeof(oc->filename), "%s", g_videoOutputFile); fmt->video_codec = (pix == bmdFormat8BitYUV ? AV_CODEC_ID_RAWVIDEO : AV_CODEC_ID_V210); fmt->audio_codec = (sample_fmt == AV_SAMPLE_FMT_S16 ? AV_CODEC_ID_PCM_S16LE : AV_CODEC_ID_PCM_S32LE); video_st = add_video_stream(oc, fmt->video_codec); audio_st = add_audio_stream(oc, fmt->audio_codec); if (serial_fd > 0) data_st = add_data_stream(oc, AV_CODEC_ID_TEXT); if (!(fmt->flags & AVFMT_NOFILE)) { if (avio_open(&oc->pb, oc->filename, AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Could not open '%s'\n", oc->filename); exit(1); } } avformat_write_header(oc, NULL); avpacket_queue_init(&queue); result = deckLinkInput->StartStreams(); if (result != S_OK) { goto bail; } // All Okay. exitStatus = 0; if (pthread_create(&th, NULL, push_packet, oc)) goto bail; // Block main thread until signal occurs pthread_mutex_lock(&sleepMutex); pthread_cond_wait(&sleepCond, &sleepMutex); pthread_mutex_unlock(&sleepMutex); deckLinkInput->StopStreams(); fprintf(stderr, "Stopping Capture\n"); avpacket_queue_end(&queue); bail: if (displayModeIterator != NULL) { displayModeIterator->Release(); displayModeIterator = NULL; } if (deckLinkInput != NULL) { deckLinkInput->Release(); deckLinkInput = NULL; } if (deckLink != NULL) { deckLink->Release(); deckLink = NULL; } if (deckLinkIterator != NULL) { deckLinkIterator->Release(); } if (oc != NULL) { av_write_trailer(oc); if (!(fmt->flags & AVFMT_NOFILE)) { /* close the output file */ avio_close(oc->pb); } } return exitStatus; }
AVWRAP_DECL int AVWrapper_Init( void (*pAddFileLogRaw)(const char*), const char* pFilename, const char* pDesc, const char* pSoundFile, const char* pFormatName, const char* pVCodecName, const char* pACodecName, int Width, int Height, int FramerateNum, int FramerateDen, int VQuality) { int ret; AddFileLogRaw = pAddFileLogRaw; av_log_set_callback( &LogCallback ); g_Width = Width; g_Height = Height; g_Framerate.num = FramerateNum; g_Framerate.den = FramerateDen; g_VQuality = VQuality; // initialize libav and register all codecs and formats av_register_all(); // find format g_pFormat = av_guess_format(pFormatName, NULL, NULL); if (!g_pFormat) return FatalError("Format \"%s\" was not found", pFormatName); // allocate the output media context g_pContainer = avformat_alloc_context(); if (!g_pContainer) return FatalError("Could not allocate output context"); g_pContainer->oformat = g_pFormat; // store description of file av_dict_set(&g_pContainer->metadata, "comment", pDesc, 0); // append extesnion to filename char ext[16]; strncpy(ext, g_pFormat->extensions, 16); ext[15] = 0; ext[strcspn(ext,",")] = 0; snprintf(g_pContainer->filename, sizeof(g_pContainer->filename), "%s.%s", pFilename, ext); // find codecs g_pVCodec = avcodec_find_encoder_by_name(pVCodecName); g_pACodec = avcodec_find_encoder_by_name(pACodecName); // add audio and video stream to container g_pVStream = NULL; g_pAStream = NULL; if (g_pVCodec) { ret = AddVideoStream(); if (ret < 0) return ret; } else Log("Video codec \"%s\" was not found; video will be ignored.\n", pVCodecName); if (g_pACodec) { g_pSoundFile = fopen(pSoundFile, "rb"); if (g_pSoundFile) { fread(&g_Frequency, 4, 1, g_pSoundFile); fread(&g_Channels, 4, 1, g_pSoundFile); AddAudioStream(); } else Log("Could not open %s\n", pSoundFile); } else Log("Audio codec \"%s\" was not found; audio will be ignored.\n", pACodecName); if (!g_pAStream && !g_pVStream) return FatalError("No video, no audio, aborting..."); // write format info to log av_dump_format(g_pContainer, 0, g_pContainer->filename, 1); // open the output file, if needed if (!(g_pFormat->flags & AVFMT_NOFILE)) { if (avio_open(&g_pContainer->pb, g_pContainer->filename, AVIO_FLAG_WRITE) < 0) return FatalError("Could not open output file (%s)", g_pContainer->filename); } // write the stream header, if any avformat_write_header(g_pContainer, NULL); g_pVFrame->pts = -1; return 0; }
int main(int argc, char **argv) { char *in_graph_desc, **out_dev_name; int nb_out_dev = 0, nb_streams = 0; AVFilterGraph *in_graph = NULL; Stream *streams = NULL, *st; AVFrame *frame = NULL; int i, j, run = 1, ret; //av_log_set_level(AV_LOG_DEBUG); if (argc < 3) { av_log(NULL, AV_LOG_ERROR, "Usage: %s filter_graph dev:out [dev2:out2...]\n\n" "Examples:\n" "%s movie=file.nut:s=v+a xv:- alsa:default\n" "%s movie=file.nut:s=v+a uncodedframecrc:pipe:0\n", argv[0], argv[0], argv[0]); exit(1); } in_graph_desc = argv[1]; out_dev_name = argv + 2; nb_out_dev = argc - 2; av_register_all(); avdevice_register_all(); avfilter_register_all(); /* Create input graph */ if (!(in_graph = avfilter_graph_alloc())) { ret = AVERROR(ENOMEM); av_log(NULL, AV_LOG_ERROR, "Unable to alloc graph graph: %s\n", av_err2str(ret)); goto fail; } ret = avfilter_graph_parse_ptr(in_graph, in_graph_desc, NULL, NULL, NULL); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Unable to parse graph: %s\n", av_err2str(ret)); goto fail; } nb_streams = 0; for (i = 0; i < in_graph->nb_filters; i++) { AVFilterContext *f = in_graph->filters[i]; for (j = 0; j < f->nb_inputs; j++) { if (!f->inputs[j]) { av_log(NULL, AV_LOG_ERROR, "Graph has unconnected inputs\n"); ret = AVERROR(EINVAL); goto fail; } } for (j = 0; j < f->nb_outputs; j++) if (!f->outputs[j]) nb_streams++; } if (!nb_streams) { av_log(NULL, AV_LOG_ERROR, "Graph has no output stream\n"); ret = AVERROR(EINVAL); goto fail; } if (nb_out_dev != 1 && nb_out_dev != nb_streams) { av_log(NULL, AV_LOG_ERROR, "Graph has %d output streams, %d devices given\n", nb_streams, nb_out_dev); ret = AVERROR(EINVAL); goto fail; } if (!(streams = av_calloc(nb_streams, sizeof(*streams)))) { ret = AVERROR(ENOMEM); av_log(NULL, AV_LOG_ERROR, "Could not allocate streams\n"); } st = streams; for (i = 0; i < in_graph->nb_filters; i++) { AVFilterContext *f = in_graph->filters[i]; for (j = 0; j < f->nb_outputs; j++) { if (!f->outputs[j]) { if ((ret = create_sink(st++, in_graph, f, j)) < 0) goto fail; } } } av_assert0(st - streams == nb_streams); if ((ret = avfilter_graph_config(in_graph, NULL)) < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to configure graph\n"); goto fail; } /* Create output devices */ for (i = 0; i < nb_out_dev; i++) { char *fmt = NULL, *dev = out_dev_name[i]; st = &streams[i]; if ((dev = strchr(dev, ':'))) { *(dev++) = 0; fmt = out_dev_name[i]; } ret = avformat_alloc_output_context2(&st->mux, NULL, fmt, dev); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to allocate output: %s\n", av_err2str(ret)); goto fail; } if (!(st->mux->oformat->flags & AVFMT_NOFILE)) { ret = avio_open2(&st->mux->pb, st->mux->filename, AVIO_FLAG_WRITE, NULL, NULL); if (ret < 0) { av_log(st->mux, AV_LOG_ERROR, "Failed to init output: %s\n", av_err2str(ret)); goto fail; } } } for (; i < nb_streams; i++) streams[i].mux = streams[0].mux; /* Create output device streams */ for (i = 0; i < nb_streams; i++) { st = &streams[i]; if (!(st->stream = avformat_new_stream(st->mux, NULL))) { ret = AVERROR(ENOMEM); av_log(NULL, AV_LOG_ERROR, "Failed to create output stream\n"); goto fail; } st->stream->codec->codec_type = st->link->type; st->stream->time_base = st->stream->codec->time_base = st->link->time_base; switch (st->link->type) { case AVMEDIA_TYPE_VIDEO: st->stream->codec->codec_id = AV_CODEC_ID_RAWVIDEO; st->stream->avg_frame_rate = st->stream-> r_frame_rate = av_buffersink_get_frame_rate(st->sink); st->stream->codec->width = st->link->w; st->stream->codec->height = st->link->h; st->stream->codec->sample_aspect_ratio = st->link->sample_aspect_ratio; st->stream->codec->pix_fmt = st->link->format; break; case AVMEDIA_TYPE_AUDIO: st->stream->codec->channel_layout = st->link->channel_layout; st->stream->codec->channels = avfilter_link_get_channels(st->link); st->stream->codec->sample_rate = st->link->sample_rate; st->stream->codec->sample_fmt = st->link->format; st->stream->codec->codec_id = av_get_pcm_codec(st->stream->codec->sample_fmt, -1); break; default: av_assert0(!"reached"); } } /* Init output devices */ for (i = 0; i < nb_out_dev; i++) { st = &streams[i]; if ((ret = avformat_write_header(st->mux, NULL)) < 0) { av_log(st->mux, AV_LOG_ERROR, "Failed to init output: %s\n", av_err2str(ret)); goto fail; } } /* Check output devices */ for (i = 0; i < nb_streams; i++) { st = &streams[i]; ret = av_write_uncoded_frame_query(st->mux, st->stream->index); if (ret < 0) { av_log(st->mux, AV_LOG_ERROR, "Uncoded frames not supported on stream #%d: %s\n", i, av_err2str(ret)); goto fail; } } while (run) { ret = avfilter_graph_request_oldest(in_graph); if (ret < 0) { if (ret == AVERROR_EOF) { run = 0; } else { av_log(NULL, AV_LOG_ERROR, "Error filtering: %s\n", av_err2str(ret)); break; } } for (i = 0; i < nb_streams; i++) { st = &streams[i]; while (1) { if (!frame && !(frame = av_frame_alloc())) { ret = AVERROR(ENOMEM); av_log(NULL, AV_LOG_ERROR, "Could not allocate frame\n"); goto fail; } ret = av_buffersink_get_frame_flags(st->sink, frame, AV_BUFFERSINK_FLAG_NO_REQUEST); if (ret < 0) { if (ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) av_log(NULL, AV_LOG_WARNING, "Error in sink: %s\n", av_err2str(ret)); break; } if (frame->pts != AV_NOPTS_VALUE) frame->pts = av_rescale_q(frame->pts, st->link ->time_base, st->stream->time_base); ret = av_interleaved_write_uncoded_frame(st->mux, st->stream->index, frame); frame = NULL; if (ret < 0) { av_log(st->stream->codec, AV_LOG_ERROR, "Error writing frame: %s\n", av_err2str(ret)); goto fail; } } } } ret = 0; for (i = 0; i < nb_out_dev; i++) { st = &streams[i]; av_write_trailer(st->mux); } fail: av_frame_free(&frame); avfilter_graph_free(&in_graph); if (streams) { for (i = 0; i < nb_out_dev; i++) { st = &streams[i]; if (st->mux) { if (st->mux->pb) avio_closep(&st->mux->pb); avformat_free_context(st->mux); } } } av_freep(&streams); return ret < 0; }
int main(int argc, char* argv[]) { AVFormatContext* pFormatCtx; AVOutputFormat* fmt; AVStream* audio_st; AVCodecContext* pCodecCtx; AVCodec* pCodec; uint8_t* frame_buf; AVFrame* pFrame; AVPacket pkt; int got_frame=0; int ret=0; int size=0; FILE *in_file=NULL; //Raw PCM data int framenum=1000; //Audio frame number const char* out_file = "tdjm.aac"; //Output URL int i; in_file= fopen("tdjm.pcm", "rb"); av_register_all(); //Method 1. pFormatCtx = avformat_alloc_context(); fmt = av_guess_format(NULL, out_file, NULL); pFormatCtx->oformat = fmt; //Method 2. //avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file); //fmt = pFormatCtx->oformat; //Open output URL if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){ printf("Failed to open output file!\n"); return -1; } audio_st = avformat_new_stream(pFormatCtx, 0); if (audio_st==NULL){ return -1; } pCodecCtx = audio_st->codec; pCodecCtx->codec_id = fmt->audio_codec; pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO; pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; pCodecCtx->sample_rate= 44100; pCodecCtx->channel_layout=AV_CH_LAYOUT_STEREO; pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout); pCodecCtx->bit_rate = 64000; //Show some information av_dump_format(pFormatCtx, 0, out_file, 1); pCodec = avcodec_find_encoder(pCodecCtx->codec_id); if (!pCodec){ printf("Can not find encoder!\n"); return -1; } if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){ printf("Failed to open encoder!\n"); return -1; } pFrame = av_frame_alloc(); pFrame->nb_samples= pCodecCtx->frame_size; pFrame->format= pCodecCtx->sample_fmt; size = av_samples_get_buffer_size(NULL, pCodecCtx->channels,pCodecCtx->frame_size,pCodecCtx->sample_fmt, 1); frame_buf = (uint8_t *)av_malloc(size); avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt,(const uint8_t*)frame_buf, size, 1); //Write Header avformat_write_header(pFormatCtx,NULL); av_new_packet(&pkt,size); for (i=0; i<framenum; i++){ //Read PCM if (fread(frame_buf, 1, size, in_file) <= 0){ printf("Failed to read raw data! \n"); return -1; }else if(feof(in_file)){ break; } pFrame->data[0] = frame_buf; //PCM Data pFrame->pts=i*100; got_frame=0; //Encode ret = avcodec_encode_audio2(pCodecCtx, &pkt,pFrame, &got_frame); if(ret < 0){ printf("Failed to encode!\n"); return -1; } if (got_frame==1){ printf("Succeed to encode 1 frame! \tsize:%5d\n",pkt.size); pkt.stream_index = audio_st->index; ret = av_write_frame(pFormatCtx, &pkt); av_free_packet(&pkt); } } //Flush Encoder ret = flush_encoder(pFormatCtx,0); if (ret < 0) { printf("Flushing encoder failed\n"); return -1; } //Write Trailer av_write_trailer(pFormatCtx); //Clean if (audio_st){ avcodec_close(audio_st->codec); av_free(pFrame); av_free(frame_buf); } avio_close(pFormatCtx->pb); avformat_free_context(pFormatCtx); fclose(in_file); return 0; }
static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) { int i, ret; AVDictionary *options = NULL; AVDictionaryEntry *entry; char *filename; char *format = NULL, *select = NULL, *on_fail = NULL; char *use_fifo = NULL, *fifo_options_str = NULL; AVFormatContext *avf2 = NULL; AVStream *st, *st2; int stream_count; int fullret; char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL; if ((ret = ff_tee_parse_slave_options(avf, slave, &options, &filename)) < 0) return ret; #define STEAL_OPTION(option, field) do { \ if ((entry = av_dict_get(options, option, NULL, 0))) { \ field = entry->value; \ entry->value = NULL; /* prevent it from being freed */ \ av_dict_set(&options, option, NULL, 0); \ } \ } while (0) STEAL_OPTION("f", format); STEAL_OPTION("select", select); STEAL_OPTION("onfail", on_fail); STEAL_OPTION("use_fifo", use_fifo); STEAL_OPTION("fifo_options", fifo_options_str); ret = parse_slave_failure_policy_option(on_fail, tee_slave); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Invalid onfail option value, valid options are 'abort' and 'ignore'\n"); goto end; } ret = parse_slave_fifo_options(use_fifo, fifo_options_str, tee_slave); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Error parsing fifo options: %s\n", av_err2str(ret)); goto end; } if (tee_slave->use_fifo) { if (options) { char *format_options_str = NULL; ret = av_dict_get_string(options, &format_options_str, '=', ':'); if (ret < 0) goto end; ret = av_dict_set(&tee_slave->fifo_options, "format_options", format_options_str, AV_DICT_DONT_STRDUP_VAL); if (ret < 0) goto end; } if (format) { ret = av_dict_set(&tee_slave->fifo_options, "fifo_format", format, AV_DICT_DONT_STRDUP_VAL); format = NULL; if (ret < 0) goto end; } av_dict_free(&options); options = tee_slave->fifo_options; } ret = avformat_alloc_output_context2(&avf2, NULL, tee_slave->use_fifo ? "fifo" :format, filename); if (ret < 0) goto end; tee_slave->avf = avf2; av_dict_copy(&avf2->metadata, avf->metadata, 0); avf2->opaque = avf->opaque; avf2->io_open = avf->io_open; avf2->io_close = avf->io_close; avf2->interrupt_callback = avf->interrupt_callback; avf2->flags = avf->flags; tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map)); if (!tee_slave->stream_map) { ret = AVERROR(ENOMEM); goto end; } stream_count = 0; for (i = 0; i < avf->nb_streams; i++) { st = avf->streams[i]; if (select) { tmp_select = av_strdup(select); // av_strtok is destructive so we regenerate it in each loop if (!tmp_select) { ret = AVERROR(ENOMEM); goto end; } fullret = 0; first_subselect = tmp_select; next_subselect = NULL; while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) { first_subselect = NULL; ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Invalid stream specifier '%s' for output '%s'\n", subselect, slave); goto end; } if (ret != 0) { fullret = 1; // match break; } } av_freep(&tmp_select); if (fullret == 0) { /* no match */ tee_slave->stream_map[i] = -1; continue; } } tee_slave->stream_map[i] = stream_count++; if (!(st2 = avformat_new_stream(avf2, NULL))) { ret = AVERROR(ENOMEM); goto end; } ret = ff_stream_encode_params_copy(st2, st); if (ret < 0) goto end; } ret = ff_format_output_open(avf2, filename, NULL); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave, av_err2str(ret)); goto end; } if ((ret = avformat_write_header(avf2, &options)) < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n", slave, av_err2str(ret)); goto end; } tee_slave->header_written = 1; tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(*tee_slave->bsfs)); if (!tee_slave->bsfs) { ret = AVERROR(ENOMEM); goto end; } entry = NULL; while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) { const char *spec = entry->key + strlen("bsfs"); if (*spec) { if (strspn(spec, slave_bsfs_spec_sep) != 1) { av_log(avf, AV_LOG_ERROR, "Specifier separator in '%s' is '%c', but only characters '%s' " "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep); ret = AVERROR(EINVAL); goto end; } spec++; /* consume separator */ } for (i = 0; i < avf2->nb_streams; i++) { ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Invalid stream specifier '%s' in bsfs option '%s' for slave " "output '%s'\n", spec, entry->key, filename); goto end; } if (ret > 0) { av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave " "output '%s'\n", spec, entry->value, i, filename); if (tee_slave->bsfs[i]) { av_log(avf, AV_LOG_WARNING, "Duplicate bsfs specification associated to stream %d of slave " "output '%s', filters will be ignored\n", i, filename); continue; } ret = av_bsf_list_parse_str(entry->value, &tee_slave->bsfs[i]); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s' associated to " "stream %d of slave output '%s'\n", entry->value, i, filename); goto end; } } } av_dict_set(&options, entry->key, NULL, 0); } for (i = 0; i < avf->nb_streams; i++){ int target_stream = tee_slave->stream_map[i]; if (target_stream < 0) continue; if (!tee_slave->bsfs[target_stream]) { /* Add pass-through bitstream filter */ ret = av_bsf_get_null_filter(&tee_slave->bsfs[target_stream]); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Failed to create pass-through bitstream filter: %s\n", av_err2str(ret)); goto end; } } tee_slave->bsfs[target_stream]->time_base_in = avf->streams[i]->time_base; ret = avcodec_parameters_copy(tee_slave->bsfs[target_stream]->par_in, avf->streams[i]->codecpar); if (ret < 0) goto end; ret = av_bsf_init(tee_slave->bsfs[target_stream]); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Failed to initialize bitstream filter(s): %s\n", av_err2str(ret)); goto end; } } if (options) { entry = NULL; while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX))) av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key); ret = AVERROR_OPTION_NOT_FOUND; goto end; } end: av_free(format); av_free(select); av_free(on_fail); av_dict_free(&options); av_freep(&tmp_select); return ret; }
int main(int argc, char **argv) { AVOutputFormat *ofmt = NULL; AVFormatContext *ifmt_ctx = NULL, *ofmt_ctx = NULL; AVPacket pkt; const char *in_filename, *out_filename; int ret, i; if (argc < 3) { printf("usage: %s input output\n" "API example program to remux a media file with libavformat and libavcodec.\n" "The output format is guessed according to the file extension.\n" "\n", argv[0]); return 1; } in_filename = argv[1]; out_filename = argv[2]; av_register_all(); if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) { fprintf(stderr, "Could not open input file '%s'", in_filename); goto end; } if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) { fprintf(stderr, "Failed to retrieve input stream information"); goto end; } av_dump_format(ifmt_ctx, 0, in_filename, 0); avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); if (!ofmt_ctx) { fprintf(stderr, "Could not create output context\n"); ret = AVERROR_UNKNOWN; goto end; } ofmt = ofmt_ctx->oformat; for (i = 0; i < ifmt_ctx->nb_streams; i++) { AVStream *in_stream = ifmt_ctx->streams[i]; AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec); if (!out_stream) { fprintf(stderr, "Failed allocating output stream\n"); ret = AVERROR_UNKNOWN; goto end; } ret = avcodec_copy_context(out_stream->codec, in_stream->codec); if (ret < 0) { fprintf(stderr, "Failed to copy context from input to output stream codec context\n"); goto end; } out_stream->codec->codec_tag = 0; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } av_dump_format(ofmt_ctx, 0, out_filename, 1); if (!(ofmt->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE); if (ret < 0) { fprintf(stderr, "Could not open output file '%s'", out_filename); goto end; } } ret = avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { fprintf(stderr, "Error occurred when opening output file\n"); goto end; } while (1) { AVStream *in_stream, *out_stream; ret = av_read_frame(ifmt_ctx, &pkt); if (ret < 0) break; in_stream = ifmt_ctx->streams[pkt.stream_index]; out_stream = ofmt_ctx->streams[pkt.stream_index]; log_packet(ifmt_ctx, &pkt, "in"); /* copy packet */ pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base); pkt.pos = -1; log_packet(ofmt_ctx, &pkt, "out"); ret = av_interleaved_write_frame(ofmt_ctx, &pkt); if (ret < 0) { fprintf(stderr, "Error muxing packet\n"); break; } av_free_packet(&pkt); } av_write_trailer(ofmt_ctx); end: avformat_close_input(&ifmt_ctx); /* close output */ if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE)) avio_closep(&ofmt_ctx->pb); avformat_free_context(ofmt_ctx); if (ret < 0 && ret != AVERROR_EOF) { fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); return 1; } return 0; }
static int open_output_file(const char *filename) { LOGI("enter open_output_file ----------------"); AVStream *out_stream; AVStream *in_stream; AVCodecContext *dec_ctx, *enc_ctx; AVCodec *encoder; int ret; unsigned int i; ofmt_ctx = NULL; avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, filename); if (!ofmt_ctx) { LOGI("Could not create output context\n"); return AVERROR_UNKNOWN; } LOGI("start avformat_find_stream_info"); for (i = 0; i < ifmt_ctx->nb_streams; i++) { out_stream = avformat_new_stream(ofmt_ctx, NULL); if (!out_stream) { LOGI("Failed allocating output stream\n"); return AVERROR_UNKNOWN; } in_stream = ifmt_ctx->streams[i]; dec_ctx = in_stream->codec; enc_ctx = out_stream->codec; dec_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; enc_ctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO || dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { /* in this example, we choose transcoding to same codec */ encoder = avcodec_find_encoder(dec_ctx->codec_id); if (!encoder) { LOGI("Necessary encoder not found\n"); return AVERROR_INVALIDDATA; } /* In this example, we transcode to same properties (picture size, * sample rate etc.). These properties can be changed for output * streams easily using filters */ if (dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO) { enc_ctx->height = dec_ctx->height; enc_ctx->width = dec_ctx->width; enc_ctx->sample_aspect_ratio = dec_ctx->sample_aspect_ratio; /* take first format from list of supported formats */ enc_ctx->pix_fmt = encoder->pix_fmts[0]; /* video time_base can be set to whatever is handy and supported by encoder */ enc_ctx->time_base = dec_ctx->time_base; } else { enc_ctx->sample_rate = dec_ctx->sample_rate; enc_ctx->channel_layout = dec_ctx->channel_layout; enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); /* take first format from list of supported formats */ enc_ctx->sample_fmt = encoder->sample_fmts[0]; enc_ctx->time_base = (AVRational){1, enc_ctx->sample_rate}; } /* Third parameter can be used to pass settings to encoder */ ret = avcodec_open2(enc_ctx, encoder, NULL); if (ret < 0) { LOGI("Cannot open video encoder for stream #%u\n", i); return ret; } } else if (dec_ctx->codec_type == AVMEDIA_TYPE_UNKNOWN) { LOGI("Elementary stream #%d is of unknown type, cannot proceed\n", i); return AVERROR_INVALIDDATA; } else { /* if this stream must be remuxed */ ret = avcodec_copy_context(ofmt_ctx->streams[i]->codec, ifmt_ctx->streams[i]->codec); if (ret < 0) { LOGI("Copying stream context failed\n"); return ret; } } if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) enc_ctx->flags |= CODEC_FLAG_GLOBAL_HEADER; } //av_dump_format(ofmt_ctx, 0, filename, 1); if (!(ofmt_ctx->oformat->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, filename, AVIO_FLAG_WRITE); if (ret < 0) { LOGI("Could not open output file '%s'", filename); return ret; } } /* init muxer, write output file header */ ret = avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { LOGI("Error occurred when opening output file\n"); return ret; } LOGI("leave open_output_file"); return 0; }
static void init_fps(int bf, int audio_preroll, int fps) { AVStream *st; ctx = avformat_alloc_context(); if (!ctx) exit(1); ctx->oformat = av_guess_format(format, NULL, NULL); if (!ctx->oformat) exit(1); ctx->pb = avio_alloc_context(iobuf, sizeof(iobuf), AVIO_FLAG_WRITE, NULL, NULL, io_write, NULL); if (!ctx->pb) exit(1); ctx->flags |= AVFMT_FLAG_BITEXACT; st = avformat_new_stream(ctx, NULL); if (!st) exit(1); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_H264; st->codec->width = 640; st->codec->height = 480; st->time_base.num = 1; st->time_base.den = 30; st->codec->extradata_size = sizeof(h264_extradata); st->codec->extradata = av_mallocz(st->codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) exit(1); memcpy(st->codec->extradata, h264_extradata, sizeof(h264_extradata)); st->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; video_st = st; st = avformat_new_stream(ctx, NULL); if (!st) exit(1); st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = AV_CODEC_ID_AAC; st->codec->sample_rate = 44100; st->codec->channels = 2; st->time_base.num = 1; st->time_base.den = 44100; st->codec->extradata_size = sizeof(aac_extradata); st->codec->extradata = av_mallocz(st->codec->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) exit(1); memcpy(st->codec->extradata, aac_extradata, sizeof(aac_extradata)); st->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; audio_st = st; if (avformat_write_header(ctx, &opts) < 0) exit(1); av_dict_free(&opts); frames = 0; gop_size = 30; duration = video_st->time_base.den / fps; audio_duration = 1024 * audio_st->time_base.den / audio_st->codec->sample_rate; if (audio_preroll) audio_preroll = 2048 * audio_st->time_base.den / audio_st->codec->sample_rate; bframes = bf; video_dts = bframes ? -duration : 0; audio_dts = -audio_preroll; }
static int write_packet(AVFormatContext *s, AVPacket *pkt) { VideoMuxData *img = s->priv_data; AVIOContext *pb[4]; char filename[1024]; AVCodecContext *codec = s->streams[pkt->stream_index]->codec; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(codec->pix_fmt); int i; int nb_renames = 0; if (!img->is_pipe) { if (img->update) { av_strlcpy(filename, img->path, sizeof(filename)); } else if (img->use_strftime) { time_t now0; struct tm *tm, tmpbuf; time(&now0); tm = localtime_r(&now0, &tmpbuf); if (!strftime(filename, sizeof(filename), img->path, tm)) { av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); return AVERROR(EINVAL); } } else if (av_get_frame_filename(filename, sizeof(filename), img->path, img->img_number) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, "Could not get frame filename number %d from pattern '%s' (either set updatefirst or use a pattern like %%03d within the filename pattern)\n", img->img_number, img->path); return AVERROR(EINVAL); } for (i = 0; i < 4; i++) { snprintf(img->tmp[i], sizeof(img->tmp[i]), "%s.tmp", filename); av_strlcpy(img->target[i], filename, sizeof(img->target[i])); if (avio_open2(&pb[i], img->use_rename ? img->tmp[i] : filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL) < 0) { av_log(s, AV_LOG_ERROR, "Could not open file : %s\n", img->use_rename ? img->tmp[i] : filename); return AVERROR(EIO); } if (!img->split_planes || i+1 >= desc->nb_components) break; filename[strlen(filename) - 1] = "UVAx"[i]; } if (img->use_rename) nb_renames = i + 1; } else { pb[0] = s->pb; } if (img->split_planes) { int ysize = codec->width * codec->height; int usize = AV_CEIL_RSHIFT(codec->width, desc->log2_chroma_w) * AV_CEIL_RSHIFT(codec->height, desc->log2_chroma_h); if (desc->comp[0].depth >= 9) { ysize *= 2; usize *= 2; } avio_write(pb[0], pkt->data , ysize); avio_write(pb[1], pkt->data + ysize , usize); avio_write(pb[2], pkt->data + ysize + usize, usize); avio_closep(&pb[1]); avio_closep(&pb[2]); if (desc->nb_components > 3) { avio_write(pb[3], pkt->data + ysize + 2*usize, ysize); avio_closep(&pb[3]); } } else if (img->muxer) { int ret; AVStream *st; AVPacket pkt2 = {0}; AVFormatContext *fmt = NULL; av_assert0(!img->split_planes); ret = avformat_alloc_output_context2(&fmt, NULL, img->muxer, s->filename); if (ret < 0) return ret; st = avformat_new_stream(fmt, NULL); if (!st) { avformat_free_context(fmt); return AVERROR(ENOMEM); } st->id = pkt->stream_index; fmt->pb = pb[0]; if ((ret = av_copy_packet(&pkt2, pkt)) < 0 || (ret = av_dup_packet(&pkt2)) < 0 || (ret = avcodec_copy_context(st->codec, s->streams[0]->codec)) < 0 || (ret = avformat_write_header(fmt, NULL)) < 0 || (ret = av_interleaved_write_frame(fmt, &pkt2)) < 0 || (ret = av_write_trailer(fmt)) < 0) { av_packet_unref(&pkt2); avformat_free_context(fmt); return ret; } av_packet_unref(&pkt2); avformat_free_context(fmt); } else { avio_write(pb[0], pkt->data, pkt->size); } avio_flush(pb[0]); if (!img->is_pipe) { avio_closep(&pb[0]); for (i = 0; i < nb_renames; i++) { ff_rename(img->tmp[i], img->target[i], s); } } img->img_number++; return 0; }
int main(int argc, char **argv) { if (argc != 5) { fprintf(stderr, "Usage: %s <segment length> <output location> <filename prefix> <encoding profile>\n", argv[0]); return 1; } struct config_info config; memset(&config, 0, sizeof(struct config_info)); config.segment_length = atoi(argv[1]); config.temp_directory = argv[2]; config.filename_prefix = argv[3]; config.encoding_profile = argv[4]; config.input_filename = "pipe://1"; char *output_filename = malloc(sizeof(char) * (strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10)); if (!output_filename) { fprintf(stderr, "Segmenter error: Could not allocate space for output filenames\n"); exit(1); } // ------------------ Done parsing input -------------- av_register_all(); AVInputFormat *input_format = av_find_input_format("mpegts"); if (!input_format) { fprintf(stderr, "Segmenter error: Could not find MPEG-TS demuxer\n"); exit(1); } AVFormatContext *input_context = NULL; int ret = avformat_open_input(&input_context, config.input_filename, input_format, NULL); if (ret != 0) { fprintf(stderr, "Segmenter error: Could not open input file, make sure it is an mpegts file: %d\n", ret); exit(1); } if (avformat_find_stream_info(input_context, NULL) < 0) { fprintf(stderr, "Segmenter error: Could not read stream information\n"); exit(1); } AVOutputFormat *output_format = av_guess_format("mpegts", NULL, NULL); if (!output_format) { fprintf(stderr, "Segmenter error: Could not find MPEG-TS muxer\n"); exit(1); } AVFormatContext *output_context = avformat_alloc_context(); if (!output_context) { fprintf(stderr, "Segmenter error: Could not allocated output context"); exit(1); } output_context->oformat = output_format; // Don't print warnings when PTS and DTS are identical. input_context->flags |= AVFMT_FLAG_IGNDTS; int video_index = -1; int audio_index = -1; AVStream *video_stream; AVStream *audio_stream; int i; for (i = 0; i < input_context->nb_streams && (video_index < 0 || audio_index < 0); i++) { switch (input_context->streams[i]->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: video_index = i; input_context->streams[i]->discard = AVDISCARD_NONE; video_stream = add_output_stream(output_context, input_context->streams[i]); break; case AVMEDIA_TYPE_AUDIO: audio_index = i; input_context->streams[i]->discard = AVDISCARD_NONE; audio_stream = add_output_stream(output_context, input_context->streams[i]); break; default: input_context->streams[i]->discard = AVDISCARD_ALL; break; } } #if LIBAVFORMAT_VERSION_MAJOR < 54 if (av_set_parameters(output_context, NULL) < 0) { fprintf(stderr, "Segmenter error: Invalid output format parameters\n"); exit(1); } #endif av_dump_format(output_context, 0, config.filename_prefix, 1); if (video_index >= 0) { AVCodec *codec = avcodec_find_decoder(video_stream->codec->codec_id); if (!codec) { fprintf(stderr, "Segmenter error: Could not find video decoder, key frames will not be honored\n"); } if (avcodec_open2(video_stream->codec, codec, NULL) < 0) { fprintf(stderr, "Segmenter error: Could not open video decoder, key frames will not be honored\n"); } } if (video_stream->codec->ticks_per_frame > 1) { // h264 sets the ticks_per_frame and time_base.den but not time_base.num // since we don't use ticks_per_frame, adjust time_base.num accordingly. video_stream->codec->time_base.num *= video_stream->codec->ticks_per_frame; } unsigned int output_index = 1; snprintf(output_filename, strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10, "%s/%s-%05u.ts", config.temp_directory, config.filename_prefix, output_index++); if (avio_open(&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Segmenter error: Could not open '%s'\n", output_filename); exit(1); } if (avformat_write_header(output_context, NULL)) { fprintf(stderr, "Segmenter error: Could not write mpegts header to first output file\n"); exit(1); } // Track initial PTS values so we can subtract them out (removing aduio/video delay, since they seem incorrect). int64_t initial_audio_pts = -1; int64_t initial_video_pts = -1; unsigned int first_segment = 1; unsigned int last_segment = 0; double prev_segment_time = 0; int decode_done; do { double segment_time; AVPacket packet; decode_done = av_read_frame(input_context, &packet); if (decode_done < 0) { break; } if (av_dup_packet(&packet) < 0) { fprintf(stderr, "Segmenter error: Could not duplicate packet"); av_free_packet(&packet); break; } if (packet.stream_index == video_index) { if (initial_video_pts < 0) initial_video_pts = packet.pts; packet.pts -= initial_video_pts; packet.dts = packet.pts; if (packet.flags & AV_PKT_FLAG_KEY) { segment_time = (double)packet.pts * video_stream->time_base.num / video_stream->time_base.den; } else { segment_time = prev_segment_time; } } else if (packet.stream_index == audio_index) { if (initial_audio_pts < 0) initial_audio_pts = packet.pts; packet.pts -= initial_audio_pts; packet.dts = packet.pts; segment_time = prev_segment_time; } else { segment_time = prev_segment_time; } // done writing the current file? if (segment_time - prev_segment_time >= config.segment_length) { avio_flush(output_context->pb); avio_close(output_context->pb); output_transfer_command(first_segment, ++last_segment, 0, config.encoding_profile); snprintf(output_filename, strlen(config.temp_directory) + 1 + strlen(config.filename_prefix) + 10, "%s/%s-%05u.ts", config.temp_directory, config.filename_prefix, output_index++); if (avio_open (&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Segmenter error: Could not open '%s'\n", output_filename); break; } prev_segment_time = segment_time; } ret = av_write_frame(output_context, &packet); if (ret < 0) { fprintf(stderr, "Segmenter error: Could not write frame of stream: %d\n", ret); } else if (ret > 0) { fprintf(stderr, "Segmenter info: End of stream requested\n"); av_free_packet(&packet); break; } av_free_packet(&packet); } while (!decode_done); av_write_trailer(output_context); if (video_index >= 0) { avcodec_close(video_stream->codec); } for (i = 0; i < output_context->nb_streams; i++) { av_freep(&output_context->streams[i]->codec); av_freep(&output_context->streams[i]); } avio_close(output_context->pb); av_free(output_context); output_transfer_command(first_segment, ++last_segment, 1, config.encoding_profile); return 0; }
static int init_filter(struct dec_audio *da, AVPacket *pkt) { struct spdifContext *spdif_ctx = da->priv; int profile = FF_PROFILE_UNKNOWN; if (spdif_ctx->codec_id == AV_CODEC_ID_DTS) profile = determine_codec_profile(da, pkt); AVFormatContext *lavf_ctx = avformat_alloc_context(); if (!lavf_ctx) goto fail; spdif_ctx->lavf_ctx = lavf_ctx; lavf_ctx->oformat = av_guess_format("spdif", NULL, NULL); if (!lavf_ctx->oformat) goto fail; void *buffer = av_mallocz(OUTBUF_SIZE); if (!buffer) abort(); lavf_ctx->pb = avio_alloc_context(buffer, OUTBUF_SIZE, 1, spdif_ctx, NULL, write_packet, NULL); if (!lavf_ctx->pb) { av_free(buffer); goto fail; } // Request minimal buffering (not available on Libav) #if LIBAVFORMAT_VERSION_MICRO >= 100 lavf_ctx->pb->direct = 1; #endif AVStream *stream = avformat_new_stream(lavf_ctx, 0); if (!stream) goto fail; stream->codecpar->codec_id = spdif_ctx->codec_id; AVDictionary *format_opts = NULL; int num_channels = 0; int sample_format = 0; int samplerate = 0; switch (spdif_ctx->codec_id) { case AV_CODEC_ID_AAC: sample_format = AF_FORMAT_S_AAC; samplerate = 48000; num_channels = 2; break; case AV_CODEC_ID_AC3: sample_format = AF_FORMAT_S_AC3; samplerate = 48000; num_channels = 2; break; case AV_CODEC_ID_DTS: { bool is_hd = profile == FF_PROFILE_DTS_HD_HRA || profile == FF_PROFILE_DTS_HD_MA || profile == FF_PROFILE_UNKNOWN; if (spdif_ctx->use_dts_hd && is_hd) { av_dict_set(&format_opts, "dtshd_rate", "768000", 0); // 4*192000 sample_format = AF_FORMAT_S_DTSHD; samplerate = 192000; num_channels = 2*4; } else { sample_format = AF_FORMAT_S_DTS; samplerate = 48000; num_channels = 2; } break; } case AV_CODEC_ID_EAC3: sample_format = AF_FORMAT_S_EAC3; samplerate = 192000; num_channels = 2; break; case AV_CODEC_ID_MP3: sample_format = AF_FORMAT_S_MP3; samplerate = 48000; num_channels = 2; break; case AV_CODEC_ID_TRUEHD: sample_format = AF_FORMAT_S_TRUEHD; samplerate = 192000; num_channels = 8; break; default: abort(); } mp_audio_set_num_channels(&spdif_ctx->fmt, num_channels); mp_audio_set_format(&spdif_ctx->fmt, sample_format); spdif_ctx->fmt.rate = samplerate; if (avformat_write_header(lavf_ctx, &format_opts) < 0) { MP_FATAL(da, "libavformat spdif initialization failed.\n"); av_dict_free(&format_opts); goto fail; } av_dict_free(&format_opts); spdif_ctx->need_close = true; return 0; fail: uninit(da); return -1; }
bool Movie::Setup() { if (!IsRecording()) return false; if (!av) return false; bool success = true; std::string err_msg; alephone::Screen *scr = alephone::Screen::instance(); view_rect = scr->window_rect(); if (MainScreenIsOpenGL()) view_rect.y = scr->height() - (view_rect.y + view_rect.h); view_rect.x *= scr->pixel_scale(); view_rect.y *= scr->pixel_scale(); view_rect.w *= scr->pixel_scale(); view_rect.h *= scr->pixel_scale(); temp_surface = SDL_CreateRGBSurface(SDL_SWSURFACE, view_rect.w, view_rect.h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0); success = (temp_surface != NULL); if (!success) err_msg = "Could not create SDL surface"; Mixer *mx = Mixer::instance(); av_register_all(); avcodec_register_all(); // Open output file AVOutputFormat *fmt; if (success) { fmt = av_guess_format("webm", NULL, NULL); success = fmt; if (!success) err_msg = "Could not find output format"; } if (success) { av->fmt_ctx = avformat_alloc_context(); success = av->fmt_ctx; if (!success) err_msg = "Could not allocate movie format context"; } if (success) { av->fmt_ctx->oformat = fmt; strncpy(av->fmt_ctx->filename, moviefile.c_str(), 1024); success = (0 <= avio_open(&av->fmt_ctx->pb, av->fmt_ctx->filename, AVIO_FLAG_WRITE)); if (!success) err_msg = "Could not open movie file for writing"; } // Open output video stream AVCodec *video_codec; AVStream *video_stream; if (success) { video_codec = avcodec_find_encoder(AV_CODEC_ID_VP8); success = video_codec; if (!success) err_msg = "Could not find VP8 encoder"; } if (success) { video_stream = avformat_new_stream(av->fmt_ctx, video_codec); success = video_stream; if (!success) err_msg = "Could not open output video stream"; } if (success) { video_stream->codec->codec_id = video_codec->id; video_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO; video_stream->codec->width = view_rect.w; video_stream->codec->height = view_rect.h; video_stream->codec->time_base = (AVRational){1, TICKS_PER_SECOND}; video_stream->codec->pix_fmt = AV_PIX_FMT_YUV420P; video_stream->codec->flags |= CODEC_FLAG_CLOSED_GOP; video_stream->codec->thread_count = get_cpu_count(); if (av->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) video_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; av->video_stream_idx = video_stream->index; // tuning options int vq = graphics_preferences->movie_export_video_quality; video_stream->codec->bit_rate = ScaleQuality(vq, 100*1024, 1024*1024, 10*1024*1024); video_stream->codec->qmin = ScaleQuality(vq, 10, 4, 0); video_stream->codec->qmax = ScaleQuality(vq, 63, 63, 50); std::string crf = boost::lexical_cast<std::string>(ScaleQuality(vq, 63, 10, 4)); av_opt_set(video_stream->codec->priv_data, "crf", crf.c_str(), 0); success = (0 <= avcodec_open2(video_stream->codec, video_codec, NULL)); if (!success) err_msg = "Could not open video codec"; } if (success) { av->video_bufsize = view_rect.w * view_rect.h * 4 + 10000; av->video_buf = static_cast<uint8_t *>(av_malloc(av->video_bufsize)); success = av->video_buf; if (!success) err_msg = "Could not allocate video buffer"; } if (success) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,0) av->video_frame = avcodec_alloc_frame(); #else av->video_frame = av_frame_alloc(); #endif success = av->video_frame; if (!success) err_msg = "Could not allocate video frame"; } if (success) { int numbytes = avpicture_get_size(video_stream->codec->pix_fmt, view_rect.w, view_rect.h); av->video_data = static_cast<uint8_t *>(av_malloc(numbytes)); success = av->video_data; if (!success) err_msg = "Could not allocate video data buffer"; } if (success) { avpicture_fill(reinterpret_cast<AVPicture *>(av->video_frame), av->video_data, video_stream->codec->pix_fmt, view_rect.w, view_rect.h); } // Open output audio stream AVCodec *audio_codec; AVStream *audio_stream; if (success) { audio_codec = avcodec_find_encoder(AV_CODEC_ID_VORBIS); success = audio_codec; if (!success) err_msg = "Could not find Vorbis encoder"; } if (success) { audio_stream = avformat_new_stream(av->fmt_ctx, audio_codec); success = audio_stream; if (!success) err_msg = "Could not open output audio stream"; } if (success) { audio_stream->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; audio_stream->codec->codec_id = audio_codec->id; audio_stream->codec->codec_type = AVMEDIA_TYPE_AUDIO; audio_stream->codec->sample_rate = mx->obtained.freq; audio_stream->codec->time_base = (AVRational){1, mx->obtained.freq}; audio_stream->codec->channels = 2; if (av->fmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) audio_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; av->audio_stream_idx = audio_stream->index; // tuning options int aq = graphics_preferences->movie_export_audio_quality; audio_stream->codec->global_quality = FF_QP2LAMBDA * (aq / 10); audio_stream->codec->flags |= CODEC_FLAG_QSCALE; audio_stream->codec->sample_fmt = AV_SAMPLE_FMT_FLTP; success = (0 <= avcodec_open2(audio_stream->codec, audio_codec, NULL)); if (!success) err_msg = "Could not open audio codec"; } if (success) { #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,0) av->audio_frame = avcodec_alloc_frame(); #else av->audio_frame = av_frame_alloc(); #endif success = av->audio_frame; if (!success) err_msg = "Could not allocate audio frame"; } if (success) { av->audio_fifo = av_fifo_alloc(262144); success = av->audio_fifo; if (!success) err_msg = "Could not allocate audio fifo"; } if (success) { av->audio_data = reinterpret_cast<uint8_t *>(av_malloc(524288)); success = av->audio_data; if (!success) err_msg = "Could not allocate audio data buffer"; } if (success) { av->audio_data_conv = reinterpret_cast<uint8_t *>(av_malloc(524288)); success = av->audio_data_conv; if (!success) err_msg = "Could not allocate audio conversion buffer"; } // initialize conversion context if (success) { av->sws_ctx = sws_getContext(temp_surface->w, temp_surface->h, AV_PIX_FMT_RGB32, video_stream->codec->width, video_stream->codec->height, video_stream->codec->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL); success = av->sws_ctx; if (!success) err_msg = "Could not create video conversion context"; } // Start movie file if (success) { video_stream->time_base = (AVRational){1, TICKS_PER_SECOND}; audio_stream->time_base = (AVRational){1, mx->obtained.freq}; avformat_write_header(av->fmt_ctx, NULL); } // set up our threads and intermediate storage if (success) { videobuf.resize(av->video_bufsize); audiobuf.resize(2 * 2 * mx->obtained.freq / 30); } if (success) { encodeReady = SDL_CreateSemaphore(0); fillReady = SDL_CreateSemaphore(1); stillEncoding = true; success = encodeReady && fillReady; if (!success) err_msg = "Could not create movie thread semaphores"; } if (success) { encodeThread = SDL_CreateThread(Movie_EncodeThread, "MovieSetup_encodeThread", this); success = encodeThread; if (!success) err_msg = "Could not create movie encoding thread"; } if (!success) { StopRecording(); std::string full_msg = "Your movie could not be exported. ("; full_msg += err_msg; full_msg += ".)"; logError(full_msg.c_str()); alert_user(full_msg.c_str()); } av->inited = success; return success; }
libav_encoder* libav_encoder::create( const char *path, unsigned width, unsigned height, const std::pair<int, int>& fps, int bit_rate ) { impl *m = new impl; for (;;) { m->format = av_guess_format(NULL, path, NULL); if (!m->format) break; if ((m->format->flags & AVFMT_NOFILE) || (m->format->video_codec == CODEC_ID_NONE)) break; m->formatCtx = avformat_alloc_context(); if (!m->formatCtx) break; m->formatCtx->oformat = m->format; { #if LIBAVFORMAT_VERSION_MAJOR >= 54 m->stream = avformat_new_stream(m->formatCtx, 0); #else m->stream = av_new_stream(m->formatCtx, 0); #endif if (!m->stream) { fprintf(stderr, "Could not alloc stream\n"); break; } m->codecCtx = m->stream->codec; m->codecCtx->codec_type = AVMEDIA_TYPE_VIDEO; if (strcmp(m->format->name, "avi") == 0) { m->codecCtx->codec_id = CODEC_ID_RAWVIDEO; } else { m->codecCtx->codec_id = m->format->video_codec; } AVCodec *codec = avcodec_find_encoder(m->codecCtx->codec_id); if (!codec) break; if (strcmp(m->format->name, "avi") == 0) { m->codecCtx->pix_fmt = PIX_FMT_BGR24; } else { if (codec->pix_fmts) m->codecCtx->pix_fmt = codec->pix_fmts[0]; else m->codecCtx->pix_fmt = PIX_FMT_YUV420P; } m->codecCtx->bit_rate = 8000000; m->codecCtx->width = width; /* resolution must be a multiple of two */ m->codecCtx->height = height; m->codecCtx->time_base.num = fps.second; m->codecCtx->time_base.den = fps.first; m->codecCtx->gop_size = 12; /* emit one intra frame every twelve frames at most */ if(m->formatCtx->oformat->flags & AVFMT_GLOBALHEADER) m->codecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; #if LIBAVFORMAT_VERSION_MAJOR >= 54 if (avcodec_open2(m->codecCtx, codec, NULL) < 0) break; #else if (avcodec_open(m->codecCtx, codec) < 0) break; #endif if (!(m->formatCtx->oformat->flags & AVFMT_RAWPICTURE)) { m->output_size = m->codecCtx->width * m->codecCtx->height * 4; m->output_buffer = (uint8_t*)av_malloc(m->output_size); } if (!alloc_frame(&m->frame1, &m->buffer1, m->codecCtx->pix_fmt, m->codecCtx->width, m->codecCtx->height)) break; if (!alloc_frame(&m->frame0, &m->buffer0, PIX_FMT_RGB32, m->codecCtx->width, m->codecCtx->height)) break; } #if LIBAVFORMAT_VERSION_MAJOR >= 54 if (avio_open(&m->formatCtx->pb, path, AVIO_FLAG_WRITE) < 0) break; avformat_write_header(m->formatCtx, NULL); #else if (url_fopen(&m->formatCtx->pb, path, URL_WRONLY) < 0) break; av_write_header(m->formatCtx); #endif m->swsCtx = sws_getContext( m->codecCtx->width, m->codecCtx->height, PIX_FMT_RGB32, m->codecCtx->width, m->codecCtx->height, m->codecCtx->pix_fmt, SWS_POINT, NULL, NULL, NULL ); if (!m->swsCtx) break; return new libav_encoder(m); } delete m; return 0; }
int video_thr(LPVOID lpParam) { int iRet = -1; AVFormatContext * pFmtCtx = NULL; AVFormatContext * pRtmpFmtCtx = NULL; AVInputFormat * pVideoInputFmt = NULL; AVOutputFormat * pVideoOutfmt = NULL; struct_stream_info * strct_streaminfo = NULL; AVCodecContext * pCodecContext = NULL; AVCodec * pCodec = NULL; int iVideoIndex = -1; int iVideo_Height = 0; int iVideo_Width = 0; int iVideoPic = 0; int64_t start_time = 0; int frame_index = 0; SDL_Event event; CLS_DlgStreamPusher* pThis = (CLS_DlgStreamPusher*)lpParam; if (pThis == NULL){ TRACE("video_thr--pThis == NULL\n"); return iRet; } pVideoInputFmt = av_find_input_format("dshow"); if (pVideoInputFmt == NULL){ TRACE("pVideoInputFmt == NULL\n"); return iRet; } char* psDevName = pThis->GetDeviceName(n_Video); if (psDevName == NULL){ TRACE("video_thr--psDevName == NULL"); return iRet; } while (1){ if (pThis->m_cstrPushAddr != ""){ break; } } //根据推流地址获取到AVFormatContext avformat_alloc_output_context2(&pRtmpFmtCtx, NULL, "flv", pThis->m_cstrPushAddr); if (NULL == pRtmpFmtCtx){ TRACE("NULL == pRtmpFmtCtx"); return iRet; } pVideoOutfmt = pRtmpFmtCtx->oformat; strct_streaminfo = pThis->m_pStreamInfo; if (NULL == strct_streaminfo){ TRACE("NULL == strct_streaminfo"); return iRet; } FILE *fp_yuv = fopen("output.yuv", "wb+"); pFmtCtx = avformat_alloc_context(); if (avformat_open_input(&pFmtCtx, psDevName, pVideoInputFmt, NULL) != 0){ TRACE("avformat_open_input err!\n"); goto END; } if (avformat_find_stream_info(pFmtCtx, NULL) < 0){ TRACE("avformat_find_stream_info(pFmtCtx, NULL) < 0\n"); goto END; } for (int i = 0; i < pFmtCtx->nb_streams; i++){ if (pFmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){ iVideoIndex = i; break; } } if (iVideoIndex < 0){ TRACE("iVideoIndex < 0\n"); goto END; } pCodecContext = pFmtCtx->streams[iVideoIndex]->codec; if (NULL == pCodecContext){ TRACE("NULL == pCodecContext"); goto END; } pCodec = avcodec_find_decoder(pCodecContext->codec_id); if (pCodec == NULL){ TRACE("avcodec_find_decoder<0"); goto END; } if (avcodec_open2(pCodecContext, pCodec, NULL)<0){ TRACE("avcodec_open2<0"); goto END; } for (int i = 0; i < pFmtCtx->nb_streams; i++) { //根据输入流创建输出流(Create output AVStream according to input AVStream) AVStream *in_stream = pFmtCtx->streams[i]; AVStream *out_stream = avformat_new_stream(pRtmpFmtCtx, in_stream->codec->codec); if (!out_stream) { printf("Failed allocating output stream\n"); iRet = AVERROR_UNKNOWN; goto END; } //复制AVCodecContext的设置(Copy the settings of AVCodecContext) iRet = avcodec_copy_context(out_stream->codec, in_stream->codec); if (iRet < 0) { TRACE("Failed to copy context from input to output stream codec context\n"); goto END; } out_stream->codec->codec_tag = 0; if (pRtmpFmtCtx->oformat->flags & AVFMT_GLOBALHEADER) out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; } if (!(pVideoOutfmt->flags & AVFMT_NOFILE)) { iRet = avio_open(&pRtmpFmtCtx->pb, pThis->m_cstrPushAddr, AVIO_FLAG_WRITE); if (iRet < 0) { TRACE("Could not open output URL '%s'", pThis->m_cstrPushAddr); goto END; } } iRet = avformat_write_header(pRtmpFmtCtx, NULL); if (iRet < 0) { TRACE("Error occurred when opening output URL\n"); goto END; } start_time = av_gettime(); //获取视频的宽与高 iVideo_Height = pCodecContext->height;//strct_streaminfo->m_height;// iVideo_Width = pCodecContext->width;//strct_streaminfo->m_width;// TRACE("video_thr--video_height[%d],video_width[%d]", iVideo_Height , iVideo_Width); strct_streaminfo->m_pVideoPacket = (AVPacket*)av_malloc(sizeof(AVPacket)); strct_streaminfo->m_pVideoFrame = av_frame_alloc(); strct_streaminfo->m_pVideoFrameYUV = av_frame_alloc(); strct_streaminfo->m_pVideoOutBuffer = (uint8_t *)av_malloc(avpicture_get_size(AV_PIX_FMT_YUV420P, iVideo_Width, iVideo_Height)); avpicture_fill((AVPicture *)strct_streaminfo->m_pVideoFrameYUV, strct_streaminfo->m_pVideoOutBuffer, AV_PIX_FMT_YUV420P, iVideo_Width, iVideo_Height); strct_streaminfo->m_video_sws_ctx = sws_getContext(iVideo_Width, iVideo_Height, pCodecContext->pix_fmt, iVideo_Width, iVideo_Height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); if (NULL == strct_streaminfo->m_video_sws_ctx){ TRACE("NULL == strct_streaminfo->m_video_sws_ctx\n"); goto END; } strct_streaminfo->m_video_refresh_tid = SDL_CreateThread(video_refresh_thread, NULL, strct_streaminfo); //从摄像头获取数据 for (;;){ AVStream *in_stream, *out_stream; SDL_WaitEvent(&event); if (event.type == FF_VIDEO_REFRESH_EVENT){ if (av_read_frame(pFmtCtx, strct_streaminfo->m_pVideoPacket) >= 0){ if (strct_streaminfo->m_pVideoPacket->pts == AV_NOPTS_VALUE){ //Write PTS AVRational time_base1 = pFmtCtx->streams[iVideoIndex]->time_base; //Duration between 2 frames (us) int64_t calc_duration = (double)AV_TIME_BASE / av_q2d(pFmtCtx->streams[iVideoIndex]->r_frame_rate); //Parameters strct_streaminfo->m_pVideoPacket->pts = (double)(frame_index*calc_duration) / (double)(av_q2d(time_base1)*AV_TIME_BASE); strct_streaminfo->m_pVideoPacket->dts = strct_streaminfo->m_pVideoPacket->pts; strct_streaminfo->m_pVideoPacket->duration = (double)calc_duration / (double)(av_q2d(time_base1)*AV_TIME_BASE); } if (strct_streaminfo->m_pVideoPacket->stream_index == iVideoIndex){ AVRational time_base = pFmtCtx->streams[iVideoIndex]->time_base; AVRational time_base_q = { 1, AV_TIME_BASE }; int64_t pts_time = av_rescale_q(strct_streaminfo->m_pVideoPacket->dts, time_base, time_base_q); int64_t now_time = av_gettime() - start_time; if (pts_time > now_time) av_usleep(pts_time - now_time); in_stream = pFmtCtx->streams[strct_streaminfo->m_pVideoPacket->stream_index]; out_stream = pRtmpFmtCtx->streams[strct_streaminfo->m_pVideoPacket->stream_index]; /* copy packet */ //转换PTS/DTS(Convert PTS/DTS) strct_streaminfo->m_pVideoPacket->pts = av_rescale_q_rnd(strct_streaminfo->m_pVideoPacket->pts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); strct_streaminfo->m_pVideoPacket->dts = av_rescale_q_rnd(strct_streaminfo->m_pVideoPacket->dts, in_stream->time_base, out_stream->time_base, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); strct_streaminfo->m_pVideoPacket->duration = av_rescale_q(strct_streaminfo->m_pVideoPacket->duration, in_stream->time_base, out_stream->time_base); strct_streaminfo->m_pVideoPacket->pos = -1; TRACE("Send %8d video frames to output URL\n", frame_index); frame_index++; iRet = av_interleaved_write_frame(pRtmpFmtCtx, strct_streaminfo->m_pVideoPacket); if (iRet < 0) { TRACE("Error muxing packet\n"); break; } if (pThis->m_blVideoShow){ //解码显示 iRet = avcodec_decode_video2(pCodecContext, strct_streaminfo->m_pVideoFrame, &iVideoPic, strct_streaminfo->m_pVideoPacket); if (iRet < 0){ TRACE("Decode Error.\n"); av_free_packet(strct_streaminfo->m_pVideoPacket); goto END; } if (iVideoPic <= 0){ TRACE("iVideoPic <= 0"); av_free_packet(strct_streaminfo->m_pVideoPacket); goto END; } if (sws_scale(strct_streaminfo->m_video_sws_ctx, (const uint8_t* const*)strct_streaminfo->m_pVideoFrame->data, strct_streaminfo->m_pVideoFrame->linesize, 0, /*strct_streaminfo->m_height*/iVideo_Height, strct_streaminfo->m_pVideoFrameYUV->data, strct_streaminfo->m_pVideoFrameYUV->linesize) < 0){ TRACE("sws_scale < 0"); av_free_packet(strct_streaminfo->m_pVideoPacket); goto END; } if (pThis->m_blPushStream){ //进行推流操作 if (pThis->push_stream() < 0){ TRACE("pThis->push_stream() < 0"); goto END; } } if (SDL_UpdateTexture(strct_streaminfo->m_sdlTexture, NULL, strct_streaminfo->m_pVideoFrameYUV->data[0], strct_streaminfo->m_pVideoFrameYUV->linesize[0]) < 0){ TRACE("SDL_UpdateTexture < 0\n"); goto END; } if (SDL_RenderClear(strct_streaminfo->m_sdlRenderer) < 0){ TRACE("SDL_RenderClear<0\n"); goto END; } if (SDL_RenderCopy(strct_streaminfo->m_sdlRenderer, strct_streaminfo->m_sdlTexture, NULL, NULL) < 0){ TRACE("SDL_RenderCopy<0\n"); goto END; } SDL_RenderPresent(strct_streaminfo->m_sdlRenderer); } } av_free_packet(strct_streaminfo->m_pVideoPacket); } } else if (event.type == FF_BREAK_EVENT){ break; } } av_write_trailer(pRtmpFmtCtx); iRet = 1; END: //fclose(fp_yuv); if (strct_streaminfo->m_video_sws_ctx){ sws_freeContext(strct_streaminfo->m_video_sws_ctx); } if (strct_streaminfo->m_pVideoFrameYUV){ av_frame_free(&strct_streaminfo->m_pVideoFrameYUV); } avformat_close_input(&pFmtCtx); avformat_free_context(pRtmpFmtCtx); return iRet; }
int main(int argc, const char *argv[]) { //input parameters FNHOLDER(inputFilename); FNHOLDER(playlistFilename); baseDirName [MAX_FILENAME_LENGTH ]=0; baseFileName[MAX_FILENAME_LENGTH ]=0; currentOutputDirName[MAX_FILENAME_LENGTH ]=0; baseFileExtension[MAX_FILENAME_LENGTH ]=0; baseFileExtension[MAXT_EXT_LENGTH]=0; //either "ts", "aac" or "mp3" int segmentLength, quiet, version,usage; FNHOLDER(tempPlaylistName); //these are used to determine the exact length of the current segment double segment_start_time = 0; unsigned int actual_segment_durations[MAX_SEGMENTS+1]; double packet_time = 0; unsigned int output_index = 1; AVOutputFormat *ofmt=NULL; AVFormatContext *ic = NULL; AVFormatContext *oc; AVStream *in_video_st = NULL; AVStream *in_audio_st = NULL; AVStream *out_video_st = NULL; AVStream *out_audio_st = NULL; AVCodec *codec; unsigned int num_segments = 0; int decode_done; int ret; int i; int listlen; int listofs=1; int persist=0; if ( parseCommandLine(argc, argv,inputFilename, playlistFilename, baseDirName, baseFileName, baseFileExtension, &segmentLength, &listlen, &quiet, &version,&usage,&persist) != 0) return 0; if (usage) printUsage(); if (version) ffmpeg_version(); if (version || usage) return 0; //fprintf(stderr, "Options parsed: inputFilename:%s playlistFilename:%s baseDirName:%s baseFileName:%s baseFileExtension:%s segmentLength:%d\n",inputFilename,playlistFilename,baseDirName,baseFileName,baseFileExtension,segmentLength ); if (listlen>0){ snprintf(tempPlaylistName, MAX_FILENAME_LENGTH, "%s/%s", baseDirName, playlistFilename); strncpy(playlistFilename, tempPlaylistName, MAX_FILENAME_LENGTH); snprintf(tempPlaylistName, MAX_FILENAME_LENGTH, "%s.tmp", playlistFilename); } //if (!quiet) av_log_set_level(AV_LOG_DEBUG); av_register_all(); avformat_network_init(); //just to be safe with later version and be able to handle all kind of input urls while(1) { ret = avformat_open_input(&ic, inputFilename, NULL, NULL); if (ret != 0) { if (persist) { sleep(1); continue; } fprintf(stderr, "Could not open input file %s. Error %d.\n", inputFilename, ret); exit(1); } if (avformat_find_stream_info(ic, NULL) < 0) { fprintf(stderr, "Could not read stream information.\n"); if (persist){ avformat_close_input(&ic); sleep(1); continue; } exit(1); } oc = avformat_alloc_context(); if (!oc) { fprintf(stderr, "Could not allocate output context."); if (persist){ avformat_close_input(&ic); sleep(1); continue; } exit(1); } int in_video_index = -1; int in_audio_index = -1; int out_video_index = -1; int out_audio_index = -1; for (i = 0; i < ic->nb_streams; i++) { switch (ic->streams[i]->codec->codec_type) { case AVMEDIA_TYPE_VIDEO: if (!out_video_st) { in_video_st=ic->streams[i]; in_video_index = i; in_video_st->discard = AVDISCARD_NONE; out_video_st = add_output_stream(oc, in_video_st); out_video_index=out_video_st->index; } break; case AVMEDIA_TYPE_AUDIO: if (!out_audio_st) { in_audio_st=ic->streams[i]; in_audio_index = i; in_audio_st->discard = AVDISCARD_NONE; out_audio_st = add_output_stream(oc, in_audio_st); out_audio_index=out_audio_st->index; } break; default: ic->streams[i]->discard = AVDISCARD_ALL; break; } } if (in_video_index == -1) { fprintf(stderr, "Source stream must have video component.\n"); if (persist){ avformat_close_input(&ic); avformat_free_context(oc); sleep(1); continue; } exit(1); } if (!ofmt) ofmt = av_guess_format("mpegts", NULL, NULL); if (!ofmt) { fprintf(stderr, "Could not find MPEG-TS muxer.\n"); exit(1); } oc->oformat = ofmt; if (oc->oformat->flags & AVFMT_GLOBALHEADER) oc->flags |= CODEC_FLAG_GLOBAL_HEADER; av_dump_format(oc, 0, baseFileName, 1); codec = avcodec_find_decoder(in_video_st->codec->codec_id); if (!codec) { fprintf(stderr, "Could not find video decoder, key frames will not be honored.\n"); } ret = avcodec_open2(in_video_st->codec, codec, NULL); if (ret < 0) { fprintf(stderr, "Could not open video decoder, key frames will not be honored.\n"); } if (listlen>0){ snprintf(currentOutputFileName, MAX_FILENAME_LENGTH, "%s/%s-%u%s", baseDirName, baseFileName, output_index, baseFileExtension); } else { //archive mode localtime_r_ex(&start_time); fillofn(); } if (avio_open(&oc->pb, currentOutputFileName,AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Could not open '%s'.\n", currentOutputFileName); exit(1); } else if (!quiet) fprintf(stderr, "Starting segment '%s'\n", currentOutputFileName); int r = avformat_write_header(oc, NULL); if (r) { fprintf(stderr, "Could not write mpegts header to first output file.\n"); debugReturnCode(r); exit(1); } int waitfirstpacket=1; time_t first_frame_sec=time(NULL); int iskeyframe=0; double vid_pts2time=(double)in_video_st->time_base.num / in_video_st->time_base.den; //double aud_pts2time=0; //if (in_audio_st) aud_pts2time=(double)in_audio_st->time_base.num / in_audio_st->time_base.den; double prev_packet_time=0; do { AVPacket packet; decode_done = av_read_frame(ic, &packet); if (decode_done < 0) { break; } //a potential memory leak: // if (av_dup_packet(&packet) < 0) { // fprintf(stderr, "Could not duplicate packet."); // av_packet_unref(&packet); // break; // } //get the most recent packet time //this time is used when the time for the final segment is printed. It may not be on the edge of //of a keyframe! if (packet.stream_index == in_video_index) { packet.stream_index = out_video_index; packet_time = (double) packet.pts * vid_pts2time; iskeyframe=packet.flags & AV_PKT_FLAG_KEY; if (iskeyframe && waitfirstpacket) { waitfirstpacket=0; prev_packet_time=packet_time; segment_start_time=packet_time; first_frame_sec=time(NULL); } } else if (packet.stream_index == in_audio_index){ packet.stream_index = out_audio_index; iskeyframe=0; } else { //how this got here?! av_packet_unref(&packet); continue; } if (waitfirstpacket) { av_packet_unref(&packet); continue; } //start looking for segment splits for videos one half second before segment duration expires. This is because the //segments are split on key frames so we cannot expect all segments to be split exactly equally. if (iskeyframe && ((packet_time - segment_start_time) >= (segmentLength - 0.25)) && (time(NULL)!=first_frame_sec)) { //a keyframe near or past segmentLength -> SPLIT avio_flush(oc->pb); avio_close(oc->pb); if (listlen>0){ actual_segment_durations[num_segments] = (unsigned int) rint(prev_packet_time - segment_start_time); num_segments++; if (num_segments>listlen) { //move list to exclude last: snprintf(currentOutputFileName, MAX_FILENAME_LENGTH, "%s/%s-%u%s", baseDirName, baseFileName, listofs, baseFileExtension); unlink (currentOutputFileName); listofs++; num_segments--; memmove(actual_segment_durations,actual_segment_durations+1,num_segments*sizeof(actual_segment_durations[0])); } write_index_file(playlistFilename, tempPlaylistName, segmentLength, num_segments,actual_segment_durations, listofs, baseFileName, baseFileExtension, (num_segments>=MAX_SEGMENTS)); if (num_segments==MAX_SEGMENTS) { fprintf(stderr, "Reached \"hard\" max segment number %u. If this is not live stream increase segment duration. If live segmenting set max list lenth (-m ...)\n", MAX_SEGMENTS); break; } output_index++; snprintf(currentOutputFileName, MAX_FILENAME_LENGTH, "%s/%s-%u%s", baseDirName, baseFileName, output_index, baseFileExtension); } else { //archive mode: localtime_r_ex(&end_time); fixofn(); } if (avio_open(&oc->pb, currentOutputFileName, AVIO_FLAG_WRITE) < 0) { fprintf(stderr, "Could not open '%s'\n", currentOutputFileName); break; } else if (!quiet) fprintf(stderr, "Starting segment '%s'\n", currentOutputFileName); fflush(stderr); segment_start_time = packet_time; first_frame_sec=time(NULL); } if (packet.stream_index == out_video_index) prev_packet_time=packet_time; ret = av_write_frame(oc, &packet); if (ret < 0) { fprintf(stderr, "Warning: Could not write frame of stream.\n"); } else if (ret > 0) { fprintf(stderr, "End of stream requested.\n"); av_packet_unref(&packet); break; } av_packet_unref(&packet); } while (!decode_done); if (in_video_st->codec->codec !=NULL) avcodec_close(in_video_st->codec); if (num_segments<MAX_SEGMENTS) { //make sure all packets are written and then close the last file. avio_flush(oc->pb); av_write_trailer(oc); for (i = 0; i < oc->nb_streams; i++) { av_freep(&oc->streams[i]->codec); av_freep(&oc->streams[i]); } avio_close(oc->pb); av_free(oc); if (num_segments>0){ actual_segment_durations[num_segments] = (unsigned int) rint(packet_time - segment_start_time); if (actual_segment_durations[num_segments] == 0) actual_segment_durations[num_segments] = 1; num_segments++; write_index_file(playlistFilename, tempPlaylistName, segmentLength, num_segments,actual_segment_durations, listofs, baseFileName, baseFileExtension, 1); } else { //archive mode localtime_r_ex(&end_time); fixofn(); } } // struct stat st; // stat(currentOutputFileName, &st); // output_bytes += st.st_size; avformat_close_input(&ic); break; } return 0; }
int cv_finance_encoder_video_input_begin( struct Encoderinfo* encoder_handle, const char* filename, //where you want to store enum AVPixelFormat pixel_format, //picture pix_format int image_width, int image_height // int image_stride ) { if (pixel_format != AV_PIX_FMT_YUV420P) { //convert to YUV420P } AVOutputFormat* fmt; AVCodec* pCodec; // set Params encoder_handle->in_w = image_width; encoder_handle->in_h = image_height; encoder_handle->framecnt = 0; encoder_handle->frameindex = 0; av_register_all(); encoder_handle->pFormatCtx = avformat_alloc_context(); //Guess Format fmt = av_guess_format(NULL, filename, NULL); encoder_handle->pFormatCtx->oformat = fmt; //Open output URL if (avio_open(&(encoder_handle->pFormatCtx->pb), filename, AVIO_FLAG_READ_WRITE) < 0) { printf("Failed to open output file! \n"); return -1; } encoder_handle->video_st = avformat_new_stream(encoder_handle->pFormatCtx, 0); encoder_handle->video_st->time_base.num = 1; encoder_handle->video_st->time_base.den = 10; if (encoder_handle->video_st == NULL) { return -1; } encoder_handle->pCodecCtx = encoder_handle->video_st->codec; //Must Param encoder_handle->pCodecCtx->codec_id = fmt->video_codec; encoder_handle->pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; encoder_handle->pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P; encoder_handle->pCodecCtx->width = encoder_handle->in_w; encoder_handle->pCodecCtx->height = encoder_handle->in_h; encoder_handle->pCodecCtx->time_base.num = 1; encoder_handle->pCodecCtx->time_base.den = 10; encoder_handle->pCodecCtx->bit_rate = 1600; encoder_handle->pCodecCtx->gop_size = 250; encoder_handle->pCodecCtx->qmin = 10; encoder_handle->pCodecCtx->qmax = 51; //Optional Param encoder_handle->pCodecCtx->max_b_frames = 3; // printf("147%d\n", AV_PIX_FMT_YUV420P); //Set Option;local var AVDictionary *param = 0; //H264 if (encoder_handle->pCodecCtx->codec_id == AV_CODEC_ID_H264) { av_dict_set(¶m, "preset", "slow", 0); av_dict_set(¶m, "tune", "zerolatency", 0); // printf("153\n"); } //av_dump_format(encoder_handle->pFormatCtx, 0, filename, 1); //open codec pCodec = avcodec_find_encoder(encoder_handle->pCodecCtx->codec_id); if (!pCodec) { printf("Can not find encoder! \n"); return -1; } if (avcodec_open2(encoder_handle->pCodecCtx, pCodec, ¶m) < 0) { printf("Failed to open encoder! \n"); return -1; } int ret; //initial frame int picture_size; encoder_handle->pFrame = av_frame_alloc(); encoder_handle->pFrame->format = encoder_handle->pCodecCtx->pix_fmt; encoder_handle->pFrame->width = encoder_handle->pCodecCtx->width; encoder_handle->pFrame->height = encoder_handle->pCodecCtx->height; picture_size=av_image_get_buffer_size(encoder_handle->pCodecCtx->pix_fmt, encoder_handle->pCodecCtx->width, encoder_handle->pCodecCtx->height,1); printf("%d:%d\n", __LINE__,picture_size); ret = av_image_alloc(encoder_handle->pFrame->data, encoder_handle->pFrame->linesize, encoder_handle->pCodecCtx->width, encoder_handle->pCodecCtx->height, encoder_handle->pCodecCtx->pix_fmt,1); // picture_size = avpicture_get_size(encoder_handle->pCodecCtx->pix_fmt, encoder_handle->pCodecCtx->width, encoder_handle->pCodecCtx->height); // uint8_t* picture_buf = (uint8_t *)av_malloc(picture_size); // avpicture_fill((AVPicture *)encoder_handle->pFrame, picture_buf, encoder_handle->pCodecCtx->pix_fmt, encoder_handle->pCodecCtx->width, encoder_handle->pCodecCtx->height); //Write File Header ret= avformat_write_header(encoder_handle->pFormatCtx, NULL); if (ret < 0) { printf("Error occurred when opening output file!\n"); return 1; } av_new_packet(&encoder_handle->pkt, picture_size); encoder_handle->y_size = encoder_handle->pCodecCtx->width * encoder_handle->pCodecCtx->height; return 0; }
int ff_example(const char *filename, const char *format) { AVOutputFormat *fmt; AVFormatContext *oc; AVStream *video_st; double video_pts; int i; fmt = av_guess_format(format, NULL, NULL); if (!fmt) { fprintf(stderr, "Could not find suitable output format\n"); exit(1); } fmt->video_codec = CODEC_ID_MJPEG; /* allocate the output media context */ oc = avformat_alloc_context(); if (!oc) { fprintf(stderr, "Memory error\n"); exit(1); } oc->oformat = fmt; snprintf(oc->filename, sizeof(oc->filename), "%s", filename); video_st = NULL; if (fmt->video_codec != CODEC_ID_NONE) video_st = add_video_stream(oc, fmt->video_codec); av_dump_format(oc, 0, filename, 1); /* now that all the parameters are set, we can open the audio and video codecs and allocate the necessary encode buffers */ if (video_st) open_video(oc, video_st); if (avio_open(&oc->pb, filename, URL_WRONLY) < 0) { fprintf(stderr, "Could not open '%s'\n", filename); exit(1); } /* write the stream header, if any */ avformat_write_header(oc, NULL); for(;;) { video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; printf("pts: %f\n", video_pts); if (frame_count > STREAM_NB_FRAMES) break; /* write interleaved audio and video frames */ if (write_video_frame(oc, video_st) < 0) break; } printf("%d frames written\n", frame_count); av_write_trailer(oc); /* close each codec */ if (video_st) close_video(oc, video_st); /* free the streams */ for(i = 0; i < oc->nb_streams; i++) { av_freep(&oc->streams[i]->codec); av_freep(&oc->streams[i]); } avio_close(oc->pb); /* free the stream */ av_free(oc); return 0; }
bool ffmpeg_save_flv::init_flv(std::string session_name, int width, int height) { // find the flv video encoder (for output) set_outer_stream_state(VSTR_OST_STATE_PENDING, ""); #if (LIBAVCODEC_VERSION_MAJOR < 54) flv_codec = avcodec_find_encoder(CODEC_ID_FLV1); #else flv_codec = avcodec_find_encoder(AV_CODEC_ID_FLV1); #endif if (!flv_codec) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "FLV1 Codec not found!", VSTR_OST_ERR_CODEC_NOT_FOUND); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } // allocate flv codec context (for output) flv_codec_context = avcodec_alloc_context3(flv_codec); if (!flv_codec_context) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "Could not allocate video FLV1 codec context!", VSTR_OST_ERR_OPEN_CODEC); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } flv_format_context = avformat_alloc_context(); flv_fmt = av_guess_format("flv", output_filename.c_str(), NULL); flv_format_context->oformat = flv_fmt; flv_stream = avformat_new_stream(flv_format_context, flv_codec); flv_stream->codec = flv_codec_context; flv_codec_context->pix_fmt = pEncodedFormat; flv_codec_context->width = width; flv_codec_context->height = height; flv_codec_context->qmin=2; flv_codec_context->qmax=32; //flv_codec_context->time_base.den = 30; //flv_codec_context->time_base.num = 1; flv_stream->time_base.den = 1000; flv_stream->time_base.num = 1; // add headers and flags for saving flv_codec_context->flags |= CODEC_FLAG_GLOBAL_HEADER; av_dump_format(flv_format_context, 0, output_filename.c_str(), 1); int ret = avio_open(&flv_format_context->pb, output_filename.c_str(), AVIO_FLAG_WRITE); if (ret < 0) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "Could not open output.", VSTR_OST_ERR_SEND_DATA); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } ret = avformat_write_header(flv_format_context, NULL); if (ret < 0) { set_outer_stream_state(VSTR_OST_STATE_ERROR, "Could not open output header.", VSTR_OST_ERR_SEND_DATA); LOG_ERR("Save Session (%s): %s \n", session_name.c_str(), state_message.c_str()); return false; } return true; }
bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { AVCodec* acodec = avcodec_find_encoder_by_name(encoder->audioCodec); AVCodec* vcodec = avcodec_find_encoder_by_name(encoder->videoCodec); if ((encoder->audioCodec && !acodec) || !vcodec || !FFmpegEncoderVerifyContainer(encoder)) { return false; } encoder->currentAudioSample = 0; encoder->currentAudioFrame = 0; encoder->currentVideoFrame = 0; encoder->nextAudioPts = 0; AVOutputFormat* oformat = av_guess_format(encoder->containerFormat, 0, 0); #ifndef USE_LIBAV avformat_alloc_output_context2(&encoder->context, oformat, 0, outfile); #else encoder->context = avformat_alloc_context(); strncpy(encoder->context->filename, outfile, sizeof(encoder->context->filename) - 1); encoder->context->filename[sizeof(encoder->context->filename) - 1] = '\0'; encoder->context->oformat = oformat; #endif if (acodec) { #ifdef FFMPEG_USE_CODECPAR encoder->audioStream = avformat_new_stream(encoder->context, NULL); encoder->audio = avcodec_alloc_context3(acodec); #else encoder->audioStream = avformat_new_stream(encoder->context, acodec); encoder->audio = encoder->audioStream->codec; #endif encoder->audio->bit_rate = encoder->audioBitrate; encoder->audio->channels = 2; encoder->audio->channel_layout = AV_CH_LAYOUT_STEREO; encoder->audio->sample_rate = encoder->sampleRate; encoder->audio->sample_fmt = encoder->sampleFormat; AVDictionary* opts = 0; av_dict_set(&opts, "strict", "-2", 0); if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) { #ifdef AV_CODEC_FLAG_GLOBAL_HEADER encoder->audio->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; #else encoder->audio->flags |= CODEC_FLAG_GLOBAL_HEADER; #endif } avcodec_open2(encoder->audio, acodec, &opts); av_dict_free(&opts); #if LIBAVCODEC_VERSION_MAJOR >= 55 encoder->audioFrame = av_frame_alloc(); #else encoder->audioFrame = avcodec_alloc_frame(); #endif if (!encoder->audio->frame_size) { encoder->audio->frame_size = 1; } encoder->audioFrame->nb_samples = encoder->audio->frame_size; encoder->audioFrame->format = encoder->audio->sample_fmt; encoder->audioFrame->pts = 0; #ifdef USE_LIBAVRESAMPLE encoder->resampleContext = avresample_alloc_context(); av_opt_set_int(encoder->resampleContext, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(encoder->resampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(encoder->resampleContext, "in_sample_rate", PREFERRED_SAMPLE_RATE, 0); av_opt_set_int(encoder->resampleContext, "out_sample_rate", encoder->sampleRate, 0); av_opt_set_int(encoder->resampleContext, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); av_opt_set_int(encoder->resampleContext, "out_sample_fmt", encoder->sampleFormat, 0); avresample_open(encoder->resampleContext); #else encoder->resampleContext = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, encoder->sampleFormat, encoder->sampleRate, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_S16, PREFERRED_SAMPLE_RATE, 0, NULL); swr_init(encoder->resampleContext); #endif encoder->audioBufferSize = (encoder->audioFrame->nb_samples * PREFERRED_SAMPLE_RATE / encoder->sampleRate) * 4; encoder->audioBuffer = av_malloc(encoder->audioBufferSize); encoder->postaudioBufferSize = av_samples_get_buffer_size(0, encoder->audio->channels, encoder->audio->frame_size, encoder->audio->sample_fmt, 0); encoder->postaudioBuffer = av_malloc(encoder->postaudioBufferSize); avcodec_fill_audio_frame(encoder->audioFrame, encoder->audio->channels, encoder->audio->sample_fmt, (const uint8_t*) encoder->postaudioBuffer, encoder->postaudioBufferSize, 0); if (encoder->audio->codec->id == AV_CODEC_ID_AAC && (strcasecmp(encoder->containerFormat, "mp4") || strcasecmp(encoder->containerFormat, "m4v") || strcasecmp(encoder->containerFormat, "mov"))) { // MP4 container doesn't support the raw ADTS AAC format that the encoder spits out #ifdef FFMPEG_USE_NEW_BSF av_bsf_alloc(av_bsf_get_by_name("aac_adtstoasc"), &encoder->absf); avcodec_parameters_from_context(encoder->absf->par_in, encoder->audio); av_bsf_init(encoder->absf); #else encoder->absf = av_bitstream_filter_init("aac_adtstoasc"); #endif } #ifdef FFMPEG_USE_CODECPAR avcodec_parameters_from_context(encoder->audioStream->codecpar, encoder->audio); #endif } #ifdef FFMPEG_USE_CODECPAR encoder->videoStream = avformat_new_stream(encoder->context, NULL); encoder->video = avcodec_alloc_context3(vcodec); #else encoder->videoStream = avformat_new_stream(encoder->context, vcodec); encoder->video = encoder->videoStream->codec; #endif encoder->video->bit_rate = encoder->videoBitrate; encoder->video->width = encoder->width; encoder->video->height = encoder->height; encoder->video->time_base = (AVRational) { VIDEO_TOTAL_LENGTH, GBA_ARM7TDMI_FREQUENCY }; encoder->video->pix_fmt = encoder->pixFormat; encoder->video->gop_size = 60; encoder->video->max_b_frames = 3; if (encoder->context->oformat->flags & AVFMT_GLOBALHEADER) { #ifdef AV_CODEC_FLAG_GLOBAL_HEADER encoder->video->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; #else encoder->video->flags |= CODEC_FLAG_GLOBAL_HEADER; #endif } if (encoder->video->codec->id == AV_CODEC_ID_H264 && (strcasecmp(encoder->containerFormat, "mp4") || strcasecmp(encoder->containerFormat, "m4v") || strcasecmp(encoder->containerFormat, "mov"))) { // QuickTime and a few other things require YUV420 encoder->video->pix_fmt = AV_PIX_FMT_YUV420P; } if (strcmp(vcodec->name, "libx264") == 0) { // Try to adaptively figure out when you can use a slower encoder if (encoder->width * encoder->height > 1000000) { av_opt_set(encoder->video->priv_data, "preset", "superfast", 0); } else if (encoder->width * encoder->height > 500000) { av_opt_set(encoder->video->priv_data, "preset", "veryfast", 0); } else { av_opt_set(encoder->video->priv_data, "preset", "faster", 0); } if (encoder->videoBitrate == 0) { av_opt_set(encoder->video->priv_data, "crf", "0", 0); encoder->video->pix_fmt = AV_PIX_FMT_YUV444P; } } avcodec_open2(encoder->video, vcodec, 0); #if LIBAVCODEC_VERSION_MAJOR >= 55 encoder->videoFrame = av_frame_alloc(); #else encoder->videoFrame = avcodec_alloc_frame(); #endif encoder->videoFrame->format = encoder->video->pix_fmt; encoder->videoFrame->width = encoder->video->width; encoder->videoFrame->height = encoder->video->height; encoder->videoFrame->pts = 0; _ffmpegSetVideoDimensions(&encoder->d, encoder->iwidth, encoder->iheight); av_image_alloc(encoder->videoFrame->data, encoder->videoFrame->linesize, encoder->video->width, encoder->video->height, encoder->video->pix_fmt, 32); #ifdef FFMPEG_USE_CODECPAR avcodec_parameters_from_context(encoder->videoStream->codecpar, encoder->video); #endif if (avio_open(&encoder->context->pb, outfile, AVIO_FLAG_WRITE) < 0) { return false; } return avformat_write_header(encoder->context, 0) >= 0; }
int save_snapshot (const char * filename, const AVCodecContext * picc, const AVFrame * pif) { int ok = 0; OutputContext * output_context = output_context_new(filename, pif); if (!output_context) { ok = -1; goto failed; } // write file header ok = avformat_write_header(output_context->format_context, NULL); if (ok != 0) { ok = 1; goto failed; } // prepare pixel convertion AVCodecContext * pcc = output_context->codec_context; struct SwsContext * psc = sws_getCachedContext(NULL, picc->width, picc->height, picc->pix_fmt, pcc->width, pcc->height, pcc->pix_fmt, SWS_BILINEAR, NULL, NULL, NULL); if (!psc) { ok = 1; goto failed; } // prepare converted picture AVFrame * pf = av_frame_alloc(); if (!pf) { ok = 1; goto close_sws; } pf->width = pcc->width; pf->height = pcc->height; pf->format = pcc->pix_fmt; ok = av_image_alloc(pf->data, pf->linesize, pcc->width, pcc->height, pcc->pix_fmt, 1); if (ok < 0) { ok = AVUNERROR(ok); goto close_frame; } // convert pixel format ok = sws_scale(psc, (const uint8_t * const *)pif->data, pif->linesize, 0, picc->height, pf->data, pf->linesize); if (ok <= 0) { ok = 1; goto close_picture; } // encode frame AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; ok = avcodec_send_frame(pcc, pf); if (ok != 0) { ok = AVUNERROR(ok); goto close_packet; } ok = avcodec_receive_packet(pcc, &pkt); if (ok != 0) { ok = AVUNERROR(ok); goto close_packet; } // NOTE does not matter in image pkt.pts = 0; pkt.dts = 0; // write encoded frame ok = av_interleaved_write_frame(output_context->format_context, &pkt); if (ok != 0) { ok = 1; goto close_file; } ok = 0; close_file: av_write_trailer(output_context->format_context); close_packet: av_packet_unref(&pkt); close_picture: av_freep(&pf->data[0]); close_frame: av_frame_free(&pf); close_sws: sws_freeContext(psc); failed: output_context_delete(&output_context); return ok; }
static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) { int i, ret; AVDictionary *options = NULL; AVDictionaryEntry *entry; char *filename; char *format = NULL, *select = NULL; AVFormatContext *avf2 = NULL; AVStream *st, *st2; int stream_count; if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0) return ret; #define STEAL_OPTION(option, field) do { \ if ((entry = av_dict_get(options, option, NULL, 0))) { \ field = entry->value; \ entry->value = NULL; /* prevent it from being freed */ \ av_dict_set(&options, option, NULL, 0); \ } \ } while (0) STEAL_OPTION("f", format); STEAL_OPTION("select", select); ret = avformat_alloc_output_context2(&avf2, NULL, format, filename); if (ret < 0) goto end; av_dict_copy(&avf2->metadata, avf->metadata, 0); tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map)); if (!tee_slave->stream_map) { ret = AVERROR(ENOMEM); goto end; } stream_count = 0; for (i = 0; i < avf->nb_streams; i++) { st = avf->streams[i]; if (select) { ret = avformat_match_stream_specifier(avf, avf->streams[i], select); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Invalid stream specifier '%s' for output '%s'\n", select, slave); goto end; } if (ret == 0) { /* no match */ tee_slave->stream_map[i] = -1; continue; } } tee_slave->stream_map[i] = stream_count++; if (!(st2 = avformat_new_stream(avf2, NULL))) { ret = AVERROR(ENOMEM); goto end; } st2->id = st->id; st2->r_frame_rate = st->r_frame_rate; st2->time_base = st->time_base; st2->start_time = st->start_time; st2->duration = st->duration; st2->nb_frames = st->nb_frames; st2->disposition = st->disposition; st2->sample_aspect_ratio = st->sample_aspect_ratio; st2->avg_frame_rate = st->avg_frame_rate; av_dict_copy(&st2->metadata, st->metadata, 0); if ((ret = avcodec_copy_context(st2->codec, st->codec)) < 0) goto end; } if (!(avf2->oformat->flags & AVFMT_NOFILE)) { if ((ret = avio_open(&avf2->pb, filename, AVIO_FLAG_WRITE)) < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave, av_err2str(ret)); goto end; } } if ((ret = avformat_write_header(avf2, &options)) < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n", slave, av_err2str(ret)); goto end; } tee_slave->avf = avf2; tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(TeeSlave)); if (!tee_slave->bsfs) { ret = AVERROR(ENOMEM); goto end; } entry = NULL; while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) { const char *spec = entry->key + strlen("bsfs"); if (*spec) { if (strspn(spec, slave_bsfs_spec_sep) != 1) { av_log(avf, AV_LOG_ERROR, "Specifier separator in '%s' is '%c', but only characters '%s' " "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep); return AVERROR(EINVAL); } spec++; /* consume separator */ } for (i = 0; i < avf2->nb_streams; i++) { ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Invalid stream specifier '%s' in bsfs option '%s' for slave " "output '%s'\n", spec, entry->key, filename); goto end; } if (ret > 0) { av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave " "output '%s'\n", spec, entry->value, i, filename); if (tee_slave->bsfs[i]) { av_log(avf, AV_LOG_WARNING, "Duplicate bsfs specification associated to stream %d of slave " "output '%s', filters will be ignored\n", i, filename); continue; } ret = parse_bsfs(avf, entry->value, &tee_slave->bsfs[i]); if (ret < 0) { av_log(avf, AV_LOG_ERROR, "Error parsing bitstream filter sequence '%s' associated to " "stream %d of slave output '%s'\n", entry->value, i, filename); goto end; } } } av_dict_set(&options, entry->key, NULL, 0); } if (options) { entry = NULL; while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX))) av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key); ret = AVERROR_OPTION_NOT_FOUND; goto end; } end: av_free(format); av_free(select); av_dict_free(&options); return ret; }
/** * Saves image data to a file in pgm or pbm format. * * @param filename file name to save image to * @param image image to save * @param type filetype of the image to save * @return true on success, false on failure */ void saveImage(char *filename, AVFrame *input, int outputPixFmt) { AVOutputFormat *fmt = NULL; enum AVCodecID output_codec = -1; AVCodec *codec; AVFormatContext *out_ctx; AVCodecContext *codec_ctx; AVStream *video_st; AVFrame *output = input; int ret; char errbuff[1024]; fmt = av_guess_format("image2", NULL, NULL); if ( !fmt ) { errOutput("could not find suitable output format."); } out_ctx = avformat_alloc_context(); if ( !out_ctx ) { errOutput("unable to allocate output context."); } out_ctx->oformat = fmt; snprintf(out_ctx->filename, sizeof(out_ctx->filename), "%s", filename); switch (outputPixFmt) { case AV_PIX_FMT_RGB24: output_codec = AV_CODEC_ID_PPM; break; case AV_PIX_FMT_Y400A: case AV_PIX_FMT_GRAY8: outputPixFmt = AV_PIX_FMT_GRAY8; output_codec = AV_CODEC_ID_PGM; break; case AV_PIX_FMT_MONOBLACK: case AV_PIX_FMT_MONOWHITE: outputPixFmt = AV_PIX_FMT_MONOWHITE; output_codec = AV_CODEC_ID_PBM; break; } if ( input->format != outputPixFmt ) { initImage(&output, input->width, input->height, outputPixFmt, -1); copyImageArea(0, 0, input->width, input->height, input, 0, 0, output); } codec = avcodec_find_encoder(output_codec); if ( !codec ) { errOutput("output codec not found"); } video_st = avformat_new_stream(out_ctx, codec); if ( !video_st ) { errOutput("could not alloc output stream"); } codec_ctx = video_st->codec; codec_ctx->width = output->width; codec_ctx->height = output->height; codec_ctx->pix_fmt = output->format; video_st->time_base.den = codec_ctx->time_base.den = 1; video_st->time_base.num = codec_ctx->time_base.num = 1; ret = avcodec_open2(codec_ctx, codec, NULL); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("unable to open codec: %s", errbuff); } if (verbose >= VERBOSE_MORE) av_dump_format(out_ctx, 0, filename, 1); if (avio_open(&out_ctx->pb, filename, AVIO_FLAG_WRITE) < 0) { errOutput("could not open '%s'", filename); } avformat_write_header(out_ctx, NULL); AVPacket pkt = { 0 }; int got_packet; av_init_packet(&pkt); /* encode the image */ ret = avcodec_encode_video2(video_st->codec, &pkt, output, &got_packet); if (ret < 0) { av_strerror(ret, errbuff, sizeof(errbuff)); errOutput("unable to write file %s: %s", filename, errbuff); } av_write_frame(out_ctx, &pkt); av_write_trailer(out_ctx); avcodec_close(codec_ctx); av_free(codec_ctx); av_free(video_st); avio_close(out_ctx->pb); av_free(out_ctx); if ( output != input ) av_frame_free(&output); }
int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, AVStream *st, URLContext *handle, int packet_size, int idx) { AVFormatContext *rtpctx = NULL; int ret; AVOutputFormat *rtp_format = av_guess_format("rtp", NULL, NULL); uint8_t *rtpflags; AVDictionary *opts = NULL; if (!rtp_format) { ret = AVERROR(ENOSYS); goto fail; } /* Allocate an AVFormatContext for each output stream */ rtpctx = avformat_alloc_context(); if (!rtpctx) { ret = AVERROR(ENOMEM); goto fail; } rtpctx->oformat = rtp_format; if (!avformat_new_stream(rtpctx, NULL)) { ret = AVERROR(ENOMEM); goto fail; } /* Pass the interrupt callback on */ rtpctx->interrupt_callback = s->interrupt_callback; /* Copy the max delay setting; the rtp muxer reads this. */ rtpctx->max_delay = s->max_delay; /* Copy other stream parameters. */ rtpctx->streams[0]->sample_aspect_ratio = st->sample_aspect_ratio; rtpctx->flags |= s->flags & AVFMT_FLAG_BITEXACT; /* Get the payload type from the codec */ if (st->id < RTP_PT_PRIVATE) rtpctx->streams[0]->id = ff_rtp_get_payload_type(s, st->codecpar, idx); else rtpctx->streams[0]->id = st->id; if (av_opt_get(s, "rtpflags", AV_OPT_SEARCH_CHILDREN, &rtpflags) >= 0) av_dict_set(&opts, "rtpflags", rtpflags, AV_DICT_DONT_STRDUP_VAL); /* Set the synchronized start time. */ rtpctx->start_time_realtime = s->start_time_realtime; avcodec_parameters_copy(rtpctx->streams[0]->codecpar, st->codecpar); rtpctx->streams[0]->time_base = st->time_base; if (handle) { ret = ffio_fdopen(&rtpctx->pb, handle); if (ret < 0) ffurl_close(handle); } else ret = ffio_open_dyn_packet_buf(&rtpctx->pb, packet_size); if (!ret) ret = avformat_write_header(rtpctx, &opts); av_dict_free(&opts); if (ret) { if (handle && rtpctx->pb) { avio_closep(&rtpctx->pb); } else if (rtpctx->pb) { ffio_free_dyn_buf(&rtpctx->pb); } avformat_free_context(rtpctx); return ret; } *out = rtpctx; return 0; fail: avformat_free_context(rtpctx); if (handle) ffurl_close(handle); return ret; }
bool VideoEncoder::init(const Desc& desc) { // Register the codecs av_register_all(); // create the output context avformat_alloc_output_context2(&mpOutputContext, nullptr, nullptr, mFilename.c_str()); if(mpOutputContext == nullptr) { // The sample tries again, while explicitly requesting mpeg format. I chose not to do it, since it might lead to a container with a wrong extension return error(mFilename, "File output format not recognized. Make sure you use a known file extension (avi/mpeg/mp4)"); } // Get the output format of the container AVOutputFormat* pOutputFormat = mpOutputContext->oformat; assert((pOutputFormat->flags & AVFMT_NOFILE) == 0); // Problem. We want a file. // create the video codec AVCodec* pVideoCodec; mpOutputStream = createVideoStream(mpOutputContext, desc.fps, getCodecID(desc.codec), mFilename, pVideoCodec); if(mpOutputStream == nullptr) { return false; } mpCodecContext = createCodecContext(mpOutputContext, desc.width, desc.height, desc.fps, desc.bitrateMbps, desc.gopSize, getCodecID(desc.codec), pVideoCodec); if(mpCodecContext == nullptr) { return false; } // Open the video stream if(openVideo(pVideoCodec, mpCodecContext, mpFrame, mFilename) == false) { return false; } // copy the stream parameters to the muxer if(avcodec_parameters_from_context(mpOutputStream->codecpar, mpCodecContext) < 0) { return error(desc.filename, "Could not copy the stream parameters\n"); } av_dump_format(mpOutputContext, 0, mFilename.c_str(), 1); // Open the output file assert((pOutputFormat->flags & AVFMT_NOFILE) == 0); // No output file required. Not sure if/when this happens. if(avio_open(&mpOutputContext->pb, mFilename.c_str(), AVIO_FLAG_WRITE) < 0) { return error(mFilename, "Can't open output file."); } // Write the stream header if(avformat_write_header(mpOutputContext, nullptr) < 0) { return error(mFilename, "Can't write file header."); } mFormat = desc.format; mRowPitch = getFormatBytesPerBlock(desc.format) * desc.width; if(desc.flipY) { mpFlippedImage = new uint8_t[desc.height * mRowPitch]; } mpSwsContext = sws_getContext(desc.width, desc.height, getPictureFormatFromFalcorFormat(desc.format), desc.width, desc.height, mpCodecContext->pix_fmt, SWS_POINT, nullptr, nullptr, nullptr); if(mpSwsContext == nullptr) { return error(mFilename, "Failed to allocate SWScale context"); } return true; }