-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathcommon-m4a.cpp
More file actions
129 lines (110 loc) · 4.23 KB
/
Copy pathcommon-m4a.cpp
File metadata and controls
129 lines (110 loc) · 4.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "common.h"
#include "common-m4a.h"
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswresample/swresample.h>
}
#include <vector>
#include <string>
bool read_m4a(const std::string &fname, std::vector<float> &pcmf32, std::vector<std::vector<float>> &pcmf32s,
bool stereo) {
avformat_network_init();
AVFormatContext *formatContext = avformat_alloc_context();
if (avformat_open_input(&formatContext, fname.c_str(), nullptr, nullptr) != 0) {
fprintf(stderr, "Could not open file %s\n", fname.c_str());
return false;
}
if (avformat_find_stream_info(formatContext, nullptr) < 0) {
fprintf(stderr, "Could not find stream information\n");
avformat_close_input(&formatContext);
return false;
}
const AVCodec *codec = nullptr;
int streamIndex = av_find_best_stream(formatContext, AVMEDIA_TYPE_AUDIO, -1, -1, &codec, 0);
if (streamIndex < 0) {
fprintf(stderr, "Could not find any audio stream in the file\n");
avformat_close_input(&formatContext);
return false;
}
AVCodecContext *codecContext = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(codecContext, formatContext->streams[streamIndex]->codecpar);
if (avcodec_open2(codecContext, codec, nullptr) < 0) {
fprintf(stderr, "Could not open codec\n");
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
return false;
}
//bool need_resample = (codecContext->sample_rate != COMMON_SAMPLE_RATE);
SwrContext *swrCtx = nullptr;
swrCtx = swr_alloc_set_opts(nullptr,
stereo ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO,
AV_SAMPLE_FMT_FLT,
COMMON_SAMPLE_RATE,
codecContext->channel_layout,
codecContext->sample_fmt,
codecContext->sample_rate,
0, nullptr);
if (!swrCtx || swr_init(swrCtx) < 0) {
fprintf(stderr, "Could not initialize the resampling context\n");
swr_free(&swrCtx);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
return false;
}
AVPacket packet;
av_init_packet(&packet);
packet.data = nullptr;
packet.size = 0;
AVFrame *frame = av_frame_alloc();
while (av_read_frame(formatContext, &packet) >= 0) {
if (packet.stream_index == streamIndex) {
//decode
int ret = avcodec_send_packet(codecContext, &packet);
if (ret < 0) {
fprintf(stderr, "Error sending packet for decoding\n");
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(codecContext, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
break;
}
// Direct processing of decoded frames
uint8_t *out_buf[2] = {nullptr, nullptr};
int out_channels = stereo ? 2 : 1;
int out_samples = av_rescale_rnd(swr_get_delay(swrCtx, codecContext->sample_rate) + frame->nb_samples,
COMMON_SAMPLE_RATE, codecContext->sample_rate, AV_ROUND_UP);
av_samples_alloc(out_buf, nullptr, out_channels, out_samples, AV_SAMPLE_FMT_FLT, 0);
swr_convert(swrCtx, out_buf, out_samples, (const uint8_t **) frame->data, frame->nb_samples);
int data_size = av_samples_get_buffer_size(nullptr, out_channels, out_samples, AV_SAMPLE_FMT_FLT, 0);
for (int i = 0; i < data_size / sizeof(float); ++i) {
pcmf32.push_back(((float *) out_buf[0])[i]);
if (stereo && out_buf[1] != nullptr) {
pcmf32s[0].push_back(((float *) out_buf[0])[i]);
pcmf32s[1].push_back(((float *) out_buf[1])[i]);
}
}
if (out_buf[0]) {
av_freep(&out_buf[0]);
}
if (stereo && out_buf[1]) {
av_freep(&out_buf[1]);
}
av_frame_unref(frame);
}
av_packet_unref(&packet);
}
av_packet_unref(&packet);
}
// Clean up
av_frame_free(&frame);
swr_free(&swrCtx);
avcodec_free_context(&codecContext);
avformat_close_input(&formatContext);
avformat_network_deinit();
return true;
}