Skip to content

Instantly share code, notes, and snippets.

@prabindh
Created May 8, 2020 04:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save prabindh/c72f31468f965013124feffc3e20dd38 to your computer and use it in GitHub Desktop.
Save prabindh/c72f31468f965013124feffc3e20dd38 to your computer and use it in GitHub Desktop.
Programmatic read Audio packets and decode from MP4
// 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;
@prabindh
Copy link
Author

prabindh commented May 8, 2020

// Register everything
av_register_all();
avformat_network_init();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment