Created
May 8, 2020 04:01
-
-
Save prabindh/c72f31468f965013124feffc3e20dd38 to your computer and use it in GitHub Desktop.
Programmatic read Audio packets and decode from MP4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Modified from - https://gist.github.com/cedricve/a7f6817c18eeb19a0716ed0ca0e037c4 | |
// Open the initial context variables that are needed | |
SwsContext *img_convert_ctx; | |
AVFormatContext* format_ctx = avformat_alloc_context(); | |
AVCodecContext* codec_ctx = NULL; | |
int audio_stream_index; | |
std::ofstream output_file; | |
int64_t last_time = 0, first_time = 0; | |
std::cout << std::endl << "Starting audio thread" << std::endl; | |
//open TCP | |
if (avformat_open_input(&format_ctx, "some-url or mp4 full path", | |
NULL, NULL) != 0) { | |
return EXIT_FAILURE; | |
} | |
if (avformat_find_stream_info(format_ctx, NULL) < 0) { | |
return EXIT_FAILURE; | |
} | |
//search audio stream | |
for (int i = 0; i < format_ctx->nb_streams; i++) { | |
if (format_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) | |
audio_stream_index = i; | |
} | |
AVPacket packet; | |
av_init_packet(&packet); | |
//open output file | |
AVFormatContext* output_ctx = avformat_alloc_context(); | |
AVStream* stream = NULL; | |
int cnt = 0; | |
//start reading packets from stream and write them to file | |
av_read_play(format_ctx); //play | |
// Get the codec | |
AVCodec *codec = NULL; | |
/* Find the audio Stream, if no audio stream are found, clean and exit */ | |
AVCodec* cdc = NULL; | |
int streamIndex = av_find_best_stream(format_ctx, AVMEDIA_TYPE_AUDIO, audio_stream_index, -1, &cdc, 0); | |
if (streamIndex < 0) | |
{ | |
char errBuf[256]; | |
std::cout << av_strerror(streamIndex, errBuf, 256); | |
std::cout << errBuf << std::endl; | |
avformat_close_input(&format_ctx); | |
std::cout << "Could not find any supported audio stream in the file" << std::endl; | |
return 1; | |
} | |
/* Open the audio stream to read data in audioStream */ | |
AVStream* audioStream = format_ctx->streams[streamIndex]; | |
/* Initialize the codec context */ | |
codec_ctx = audioStream->codec; | |
codec_ctx->codec = cdc; | |
/* Open the codec, and verify if it has opened */ | |
if (avcodec_open2(codec_ctx, codec_ctx->codec, NULL) != 0) | |
{ | |
avformat_close_input(&format_ctx); | |
std::cout << "Couldn't open the context with the audio decoder" << std::endl; | |
return 1; | |
} | |
if (avcodec_open2(codec_ctx, codec, NULL) < 0) | |
{ | |
std::cout << "audio: avcodec_open2 failed"; | |
exit(1); | |
} | |
AVFrame* audio = av_frame_alloc(); | |
// size = samples/ch * 2 bytes/sample * 2 ch | |
int audio_buffer_size = (codec_ctx->frame_size * 2) * 2; // TODO | |
uint8_t* audio_buffer = (uint8_t*)(av_malloc(audio_buffer_size)); | |
avcodec_fill_audio_frame(audio, 2, codec_ctx->sample_fmt, audio_buffer, audio_buffer_size, 0); | |
double timeBase = av_q2d(format_ctx->streams[audio_stream_index]->time_base); | |
std::cout << "this is the timebase: " << timeBase << std::endl; | |
while (av_read_frame(format_ctx, &packet) >= 0 && !bQuit) //&& cnt < 1000) { //read ~ 1000 frames | |
{ | |
// std::cout << "1 Frame: " << cnt << std::endl; | |
if (packet.stream_index == audio_stream_index) | |
{ | |
//packet is audio | |
int check = 0; | |
packet.stream_index = audio_stream_index; | |
int result = avcodec_decode_audio4(codec_ctx, audio, &check, &packet); | |
if (result <= 0) | |
{ | |
std::cout << "No audio decode result" << std::endl; | |
continue; | |
} | |
last_time = packet.dts * timeBase; |
Author
prabindh
commented
May 8, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment