/* 雷霄驊
FIX: H.264 in some container format (FLV, MP4, MKV etc.) need "h264_mp4toannexb" bitstream filter (BSF)
* Add SPS,PPS in front of IDR frame
* Add start code ("0,0,0,1") in front of NALU
H.264 in some container (MPEG2TS) don't need this BSF.
*/
//'1': Use H.264 Bitstream Filter
#define USE_H264BSF 1
/* 雷霄驊
FIX:AAC in some container format (FLV, MP4, MKV etc.) need "aac_adtstoasc" bitstream filter (BSF)
*/
//'1': Use AAC Bitstream Filter
#define USE_AACBSF 1
int main(int argc, char* argv[])
{
// Variables Definition
AVFormatContext* ifmt_ctx = NULL; // Format context of input stream
const char* input_filepath = NULL; // File path of input stream
int idx_audio = -1; // index of input audio stream
int idx_video = -1; // index of input video stream
AVStream* pAudioStream = NULL; // Stream structure of input audio stream
AVStream* pVideoStream = NULL; // ... of input video stream
AVFormatContext* ofmt_ctx = NULL; // Format context of output stream
AVStream* pAudioStream_out = NULL; // Output audio stream (AAC)
AVStream* pVideoStream_out = NULL; // Output video stream (H264)
const char* output_filepath = NULL; // File path of output stream
AVPacket ipkt = { 0 }; //
// Variables Definition end
// Initialize libavformat and register all the muxers, demuxers and *protocols
av_register_all();
// Do global initialization of network components
avformat_network_init();
// Open an input stream and read the header. The codecs are not opened.
if (avformat_open_input(&ifmt_ctx, input_filepath, NULL, NULL) < 0)
{
printf("error: avformat_open_input\n");
goto END;
}
// Read packets of a media file to get stream information.
if (avformat_find_stream_info(ifmt_ctx, NULL) < 0)
{
printf("error: avformat_find_stream_info\n");
goto END;
}
// Find the stream in the file.
for (int i = 0; i < ifmt_ctx->nb_streams; i++)
{
// audio stream
if (AVMEDIA_TYPE_AUDIO == ifmt_ctx->streams[i]->codec->codec_type)
{
idx_audio = i;
}
// video stream
else if (AVMEDIA_TYPE_VIDEO == ifmt_ctx->streams[i]->codec->codec_type)
{
idx_video = i;
}
else
{
break;
}
}
if (idx_video < 0 || idx_audio < 0)
{
printf("error: can not find any audio stream or video stream\n");
goto END;
}
// input audio stream and input video stream
pAudioStream = ifmt_ctx->streams[idx_audio];
pVideoStream = ifmt_ctx->streams[idx_video];
// Allocate an AVFormatContext for an output format.
avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", output_filepath);
if (NULL == ofmt_ctx)
{
printf("error: avformat_alloc_output_context2, output stream\n");
goto END;
}
// Add a new stream to a media file.
pAudioStream_out = avformat_new_stream(ofmt_ctx, NULL);
if (NULL == pAudioStream_out)
{
printf("error: avformat_new_stream, output audio\n");
goto END;
}
// Copy the settings of the source AVCodecContext into the destination AVCodecContext.
if (avcodec_copy_context(pAudioStream_out->codec, pAudioStream->codec) < 0)
{
printf("error: avcodec_copy_context, output audio\n");
goto END;
}
// Create and initialize a AVIOContext for accessing the resource.
if (avio_open(&ofmt_ctx->pb, output_filepath, AVIO_FLAG_WRITE) < 0)
{
printf("error: avio_open, output stream\n");
goto END;
}
// Allocate the stream private data and write the stream header to an output media file.
if (avformat_write_header(ofmt_ctx, NULL) < 0)
{
printf("error: avformat_write_header, output stream\n");
goto END;
}
// Print detailed information about the input or output format.
av_dump_format(ifmt_ctx, -1, input_filepath, 0);
av_dump_format(ofmt_ctx, -1, output_filepath, 1);
#if USE_H264BSF
// Create and initialize a bitstream filter context given a bitstream filter name.
AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
#endif
// Write the stream trailer to an output media file and free the file private data.
if (0 != av_write_trailer(ofmt_ctx))
{
printf("error: av_write_trailer\n");
goto END;
}