Hi to all guys, I don’t understand what I do wrong? I saw all examples, saw headers with API description… Where is my fault?
To begin with this, my code: #include <libavdevice/avdevice.h> #include <libswscale/swscale.h> #include <libswresample/swresample.h> #include <libavutil/imgutils.h> int open_input_device(AVFormatContext **ifmt_ctx, const char* device_name, AVInputFormat **ifmt, AVDictionary *iopt) { // Open input video file if (avformat_open_input(ifmt_ctx, device_name, *ifmt, &iopt) != 0) { printf("%s\n", "Couldn't open input file"); return -1; } // Retrieve stream information if (avformat_find_stream_info(*ifmt_ctx, NULL) < 0) { printf("%s\n", "Couldn't find stream information"); return -1; } // Dump information about input media onto standard error av_dump_format(*ifmt_ctx, 0, device_name, 0); return 0; } int main(void) { /* Inputs */ AVFormatContext *ifmt_ctx = NULL; AVInputFormat *ifmt = NULL; AVDictionary *iopt = NULL; AVDictionary *libx264opt = NULL; AVCodec *ivcdc = NULL; AVCodecContext *ivcdc_ctx = NULL; AVCodec *iacdc = NULL; AVCodecContext *iacdc_ctx = NULL; AVPacket ipkt; /* Outputs */ const char *rtmpUrl = "test.flv"; AVFormatContext *ofmt_ctx; AVOutputFormat *ofmt; AVCodec *ovcdc = NULL; AVCodecContext *ovcdc_ctx = NULL; AVCodec *oacdc = NULL; AVCodecContext *oacdc_ctx = NULL; AVPacket opkt; /* Utils */ int i, ret = -1, vindex = -1, aindex = -1; av_register_all(); avformat_network_init(); avdevice_register_all(); avcodec_register_all(); //Grab AVFoundation settings ifmt = av_find_input_format("avfoundation"); av_dict_set(&iopt, "video_size", "1280x720", 0); av_dict_set(&iopt, "probesize", "100M", 0); av_dict_set(&iopt, "analyzeduration", "100M", 0); open_input_device(&ifmt_ctx, "0:1", &ifmt, iopt); ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", rtmpUrl); if (!ofmt_ctx || ret < 0) { printf("%s\n", "Can't allocate the output media context"); return -1; } ofmt_ctx->probesize = 100000000; ofmt_ctx->max_analyze_duration = 100000000; ofmt = ofmt_ctx->oformat; ofmt->video_codec = AV_CODEC_ID_H264; ofmt->audio_codec = AV_CODEC_ID_MP3; ofmt->flags |= AVFMT_GLOBALHEADER; for (i = 0; i < ifmt_ctx->nb_streams; i++) { if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { vindex = i; ivcdc = avcodec_find_decoder(ifmt_ctx->streams[i]-> codecpar->codec_id); if (!ivcdc) { printf("%s\n", "Failed to find decoder for input video stream"); return -1; } ivcdc_ctx = avcodec_alloc_context3(ivcdc); if (!ivcdc_ctx) { printf("%s\n", "Failed to allocate the decoder context for input video stream"); return -1; } ret = avcodec_parameters_to_context(ivcdc_ctx, ifmt_ctx-> streams[i]->codecpar); if (ret < 0) { printf("%s\n", "Failed to copy decoder parameters to video input decoder context"); return -1; } /* Open decoder */ ret = avcodec_open2(ivcdc_ctx, ivcdc, NULL); if (ret < 0) { printf("%s\n", "Failed to open decoder for video input stream"); return -1; } // Output ovcdc = avcodec_find_encoder(ofmt->video_codec); if (!ovcdc) { printf("%s\n", "Failed to find encoder for output video stream"); return -1; } ovcdc_ctx = avcodec_alloc_context3(ovcdc); if (!ovcdc_ctx) { printf("%s\n", "Failed to allocate the encoder context for output video stream"); return -1; } ovcdc_ctx->width = 1280; ovcdc_ctx->height = 720; ovcdc_ctx->coded_width = 1280; ovcdc_ctx->coded_height = 720; ovcdc_ctx->bit_rate = 2000000; ovcdc_ctx->gop_size = 60; ovcdc_ctx->pix_fmt = AV_PIX_FMT_YUV422P; ovcdc_ctx->time_base = (AVRational){1, 30}; ovcdc_ctx->framerate = (AVRational){30, 1}; if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { ovcdc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } AVStream *ost = avformat_new_stream(ofmt_ctx, ovcdc); if (!ost) { printf("%s\n", "Failed add new video stream to output"); return -1; } ost->id = ofmt_ctx->nb_streams - 1; ret = avcodec_parameters_from_context(ost->codecpar, ovcdc_ctx); if (ret < 0) { printf("%s\n", "Failed to copy video encoder parameters to output video encoder context"); return -1; } ost->avg_frame_rate = ovcdc_ctx->framerate; ost->r_frame_rate = ovcdc_ctx->framerate; ost->time_base = ovcdc_ctx->time_base; /* Open encoder */ av_dict_set(&libx264opt, "profile:v", "high422", 0); av_dict_set(&libx264opt, "level", "41", 0); av_dict_set(&libx264opt, "preset", "ultrafast", 0); av_dict_set(&libx264opt, "tune", "zerolatency", 0); av_dict_set(&libx264opt, "crf", "23", 0); av_dict_set(&libx264opt, "g", "60", 0); av_dict_set(&libx264opt, "maxrate", "2500k", 0); av_dict_set(&libx264opt, "bufsize", "2500k", 0); ret = avcodec_open2(ovcdc_ctx, ovcdc, &libx264opt); if (ret < 0) { printf("%s\n", "Failed to open encoder for video output stream"); return -1; } } else if (ifmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { aindex = i; iacdc = avcodec_find_decoder(ifmt_ctx->streams[i]-> codecpar->codec_id); if (!iacdc) { printf("%s\n", "Failed to find decoder for input audio stream"); return -1; } iacdc_ctx = avcodec_alloc_context3(iacdc); if (!iacdc_ctx) { printf("%s\n", "Failed to allocate the decoder context for input audio stream"); return -1; } ret = avcodec_parameters_to_context(iacdc_ctx, ifmt_ctx-> streams[i]->codecpar); if (ret < 0) { printf("%s\n", "Failed to copy decoder parameters to audio input decoder context"); return -1; } /* Open decoder */ ret = avcodec_open2(iacdc_ctx, iacdc, NULL); if (ret < 0) { printf("%s\n", "Failed to open decoder for audio input stream"); return -1; } // Output oacdc = avcodec_find_encoder(ofmt->audio_codec); if (!oacdc) { printf("%s\n", "Failed to find encoder for output audio stream"); return -1; } oacdc_ctx = avcodec_alloc_context3(oacdc); if (!oacdc_ctx) { printf("%s\n", "Failed to allocate the encoder context for output audio stream"); return -1; } oacdc_ctx->sample_fmt = oacdc->sample_fmts ? oacdc->sample_fmts[0] : AV_SAMPLE_FMT_FLTP; oacdc_ctx->bit_rate = 192000; if (oacdc->supported_samplerates) { oacdc_ctx->sample_rate = oacdc->supported_samplerates[0]; for (int j = 0; oacdc->supported_samplerates[j]; j++) { if (oacdc->supported_samplerates[j] == 44100) oacdc_ctx->sample_rate = 44100; } } oacdc_ctx->channels = av_get_channel_layout_nb_channels(iacdc_ctx-> channel_layout); if (oacdc->channel_layouts) { oacdc_ctx->channel_layout = oacdc->channel_layouts[0]; for (int j = 0; oacdc->channel_layouts[j]; j++) { if (oacdc->channel_layouts[j] == AV_CH_LAYOUT_STEREO) oacdc_ctx->channel_layout = AV_CH_LAYOUT_STEREO; } } if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER) { oacdc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; } AVStream *ost = avformat_new_stream(ofmt_ctx, oacdc); if (!ost) { printf("%s\n", "Failed add new audio stream to output"); return -1; } ost->id = ofmt_ctx->nb_streams - 1; ret = avcodec_parameters_from_context(ost->codecpar, oacdc_ctx); if (ret < 0) { printf("%s\n", "Failed to copy audio encoder parameters to output audio encoder context"); return -1; } ost->time_base = (AVRational){1, oacdc_ctx->sample_rate}; /* Open encoder */ ret = avcodec_open2(oacdc_ctx, oacdc, NULL); if (ret < 0) { printf("%s\n", "Failed to open encoder for audio output stream"); return -1; } } } if (vindex == -1 || aindex == -1) { printf("%s\n", "Didn't find a video or audio input stream"); return -1; } /* open the output file, if needed */ if (!(ofmt_ctx->flags & AVFMT_NOFILE)) { ret = avio_open(&ofmt_ctx->pb, rtmpUrl, AVIO_FLAG_WRITE); if (ret < 0) { printf("Could not open '%s': %s\n", rtmpUrl, av_err2str(ret)); return -1; } } /* Write the stream header, if any. */ ret = avformat_write_header(ofmt_ctx, NULL); if (ret < 0) { printf("Error occurred when opening output file: %s\n", av_err2str(ret)); return -1; } // Dump information about output media onto standard error av_dump_format(ofmt_ctx, 0, rtmpUrl, 1); // Init frames for streaming loop AVFrame *ivframe = av_frame_alloc(); AVFrame *ovframe_yuv422p = av_frame_alloc(); ovframe_yuv422p->width = ovcdc_ctx->width; ovframe_yuv422p->height = ovcdc_ctx->height; ovframe_yuv422p->format = ovcdc_ctx->pix_fmt; int numBytes; numBytes = av_image_get_buffer_size(ovframe_yuv422p->format, ovframe_yuv422p->width, ovframe_yuv422p->height, 32); if (numBytes < 0) { printf("%s\n", "Didn't count number of bytes for buffer in process of convertation to yuv422p"); return -1; } uint8_t *buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); ret = av_image_fill_arrays(ovframe_yuv422p->data, ovframe_yuv422p-> linesize, buffer, ovframe_yuv422p->format, ovframe_yuv422p->width, ovframe_yuv422p->height, 32); if (ret < 0) { printf("%s\n", "Error occured in av_image_fill_arrays()"); return -1; } struct SwsContext *sws_ctx = sws_getContext(ivcdc_ctx->width, ivcdc_ctx->height, ivcdc_ctx->pix_fmt, ovframe_yuv422p->width, ovframe_yuv422p->height, ovframe_yuv422p->format, SWS_BILINEAR, NULL, NULL, NULL); if (!sws_ctx) { printf("%s\n", "Error occured in sws_getContext()"); return -1; } AVFrame *iaframe = av_frame_alloc(); AVFrame *oaframe = av_frame_alloc(); oaframe->format = oacdc_ctx->sample_fmt; oaframe->channel_layout = oacdc_ctx->channel_layout; oaframe->sample_rate = oacdc_ctx->sample_rate; if (oacdc_ctx->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) { oaframe->nb_samples = 10000; } else { oaframe->nb_samples = oacdc_ctx->frame_size; } if (oaframe->nb_samples) { ret = av_frame_get_buffer(oaframe, 0); if (ret < 0) { printf("%s\n", "Error allocating an audio buffer"); return -1; } } struct SwrContext *swr_ctx = swr_alloc(); if (!swr_ctx) { printf("%s\n", "Could not allocate resampler context"); return -1; } /* set options */ av_opt_set_int(swr_ctx, "in_channel_count", iacdc_ctx->channels, 0); av_opt_set_int(swr_ctx, "in_sample_rate", iacdc_ctx->sample_rate, 0); av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", iacdc_ctx->sample_fmt, 0); av_opt_set_int(swr_ctx, "out_channel_count", oacdc_ctx->channels, 0); av_opt_set_int(swr_ctx, "out_sample_rate", oacdc_ctx->sample_rate, 0); av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", oacdc_ctx->sample_fmt, 0); /* initialize the resampling context */ if ((ret = swr_init(swr_ctx)) < 0) { printf("%s\n", "Failed to initialize the resampling context"); return -1; } while (av_read_frame(ifmt_ctx, &ipkt) >= 0) { if (ipkt.stream_index == vindex) { ret = avcodec_send_packet(ivcdc_ctx, &ipkt); if (ret != 0) { printf("%s\n", "Error on send packet to decoder"); printf("%s\n", av_err2str(ret)); } ret = avcodec_receive_frame(ivcdc_ctx, ivframe); if (ret != 0) { printf("%s\n", "Error on recieve frame from decoder"); printf("%s\n", av_err2str(ret)); } ovframe_yuv422p->pict_type = ivframe->pict_type; ovframe_yuv422p->key_frame = ivframe->key_frame; ovframe_yuv422p->pts = ivframe->pts; ovframe_yuv422p->pkt_dts = ivframe->pkt_dts; ovframe_yuv422p->pts = av_rescale_q(ovframe_yuv422p-> pts, ifmt_ctx->streams[vindex]->time_base, ofmt_ctx->streams[vindex]->time_base); // change to yuv422p sws_scale(sws_ctx, (uint8_t const * const *)ivframe->data, ivframe->linesize, 0, ivcdc_ctx->height, ovframe_yuv422p->data, ovframe_yuv422p->linesize); // encode to libx264 ret = avcodec_send_frame(ovcdc_ctx, ovframe_yuv422p); if (ret != 0) { printf("%s\n", "Error on send frame to encoder"); printf("%s\n", av_err2str(ret)); } do { ret = avcodec_receive_packet(ovcdc_ctx, &opkt); if (ret < 0) { if (ret != AVERROR(EAGAIN)) { printf("%s\n", "Error on recieve packet from encoder"); printf("%s\n", av_err2str(ret)); } break; } opkt.stream_index = ipkt.stream_index; av_packet_rescale_ts(&opkt, ifmt_ctx->streams[vindex]->time_base, ofmt_ctx->streams[vindex]->time_base); ret = av_interleaved_write_frame(ofmt_ctx, &opkt); if (ret < 0) { printf("%s\n", "Error muxing video packet"); break; } } while (ret >= 0); } else if (ipkt.stream_index == aindex) { ret = avcodec_send_packet(iacdc_ctx, &ipkt); if (ret != 0) { printf("%s\n", "Error on send packet to decoder(audio)"); printf("%s\n", av_err2str(ret)); } ret = avcodec_receive_frame(iacdc_ctx, iaframe); if (ret != 0) { printf("%s\n", "Error on recieve frame from decoder(audio)"); printf("%s\n", av_err2str(ret)); } /* convert to destination format */ ret = swr_convert(swr_ctx, oaframe->data, oaframe->nb_samples, (const uint8_t **)iaframe->data, iaframe->nb_samples); if (ret < 0) { printf("%s\n", "Error while converting audio frame"); break; } oaframe->pts = iaframe->pts; oaframe->pkt_dts = iaframe->pkt_dts; oaframe->pts = av_rescale_q(oaframe->pts, ifmt_ctx->streams[aindex]->time_base, ofmt_ctx->streams[aindex]->time_base); ret = avcodec_send_frame(oacdc_ctx, oaframe); if (ret != 0) { printf("%s\n", "Error on send frame to encoder"); printf("%s\n", av_err2str(ret)); } do { ret = avcodec_receive_packet(oacdc_ctx, &opkt); if (ret < 0) { if (ret != AVERROR(EAGAIN)) { printf("%s\n", "Error on recieve packet from encoder"); printf("%s\n", av_err2str(ret)); } break; } opkt.stream_index = ipkt.stream_index; av_packet_rescale_ts(&opkt, ifmt_ctx->streams[aindex]->time_base, ofmt_ctx->streams[aindex]->time_base); ret = av_interleaved_write_frame(ofmt_ctx, &opkt); if (ret < 0) { printf("%s\n", "Error muxing audio packet"); break; } } while (ret >= 0); } av_packet_unref(&ipkt); } … free resources... I don’t understand why my output file don’t have a keyframe and video codec info, what’s I do wrong? So sorry if something is wrong, it’s my first letter to community and thanks at all. Kind Regards, Valeriy V Shtoma _______________________________________________ Libav-user mailing list Libav-user@ffmpeg.org http://ffmpeg.org/mailman/listinfo/libav-user