Skip to content

Commit 0d25752

Browse files
add audio transcoding
it was tested with aac
1 parent 3b6a644 commit 0d25752

1 file changed

Lines changed: 84 additions & 2 deletions

File tree

3_transcoding.c

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ typedef struct StreamingParams {
1414
char copy_audio;
1515
char fragmented_mp4;
1616
char *video_codec;
17+
char *audio_codec;
1718
} StreamingParams;
1819

1920
typedef struct StreamingContext {
@@ -110,6 +111,37 @@ int prepare_encoder(StreamingContext *sc, AVCodecContext *decoder_ctx, AVRationa
110111
return 0;
111112
}
112113

114+
int prepare_audio_encoder(StreamingContext *sc, int sample_rate, StreamingParams sp){
115+
sc->audio_avs = avformat_new_stream(sc->avfc, NULL);
116+
117+
char *codec = "aac";
118+
if (sp.audio_codec)
119+
codec = sp.audio_codec;
120+
121+
sc->audio_avc = avcodec_find_encoder_by_name(codec);
122+
if (!sc->audio_avc) {logging("could not find the proper codec"); return -1;}
123+
124+
sc->audio_avcc = avcodec_alloc_context3(sc->audio_avc);
125+
if (!sc->audio_avcc) {logging("could not allocated memory for codec context"); return -1;}
126+
127+
int OUTPUT_CHANNELS = 2;
128+
int OUTPUT_BIT_RATE = 196000;
129+
sc->audio_avcc->channels = OUTPUT_CHANNELS;
130+
sc->audio_avcc->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS);
131+
sc->audio_avcc->sample_rate = sample_rate;
132+
sc->audio_avcc->sample_fmt = sc->audio_avc->sample_fmts[0];
133+
sc->audio_avcc->bit_rate = OUTPUT_BIT_RATE;
134+
135+
sc->audio_avcc->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;
136+
137+
sc->audio_avs->time_base.den = sample_rate;
138+
sc->audio_avs->time_base.num = 1;
139+
140+
if (avcodec_open2(sc->audio_avcc, sc->audio_avc, NULL) < 0) {logging("could not open the codec"); return -1;}
141+
avcodec_parameters_from_context(sc->audio_avs->codecpar, sc->audio_avcc);
142+
return 0;
143+
}
144+
113145
int prepare_copy(AVFormatContext *avfc, AVStream **avs, AVCodecParameters *decoder_par) {
114146
*avs = avformat_new_stream(avfc, NULL);
115147
avcodec_parameters_copy((*avs)->codecpar, decoder_par);
@@ -140,6 +172,7 @@ int encode(StreamingContext *decoder, StreamingContext *encoder, AVFrame *input_
140172
output_packet->stream_index = decoder->video_index;
141173
output_packet->duration = encoder->video_avs->time_base.den / encoder->video_avs->time_base.num / decoder->video_avs->avg_frame_rate.num * decoder->video_avs->avg_frame_rate.den;
142174

175+
143176
av_packet_rescale_ts(output_packet, decoder->video_avs->time_base, encoder->video_avs->time_base);
144177
response = av_interleaved_write_frame(encoder->avfc, output_packet);
145178
if (response != 0) { logging("Error %d while receiving packet from decoder: %s", response, av_err2str(response)); return -1;}
@@ -149,6 +182,53 @@ int encode(StreamingContext *decoder, StreamingContext *encoder, AVFrame *input_
149182
return 0;
150183
}
151184

185+
int encode_audio(StreamingContext *decoder, StreamingContext *encoder, AVFrame *input_frame) {
186+
AVPacket *output_packet = av_packet_alloc();
187+
if (!output_packet) {logging("could not allocate memory for output packet"); return -1;}
188+
189+
int response = avcodec_send_frame(encoder->audio_avcc, input_frame);
190+
191+
while (response >= 0) {
192+
response = avcodec_receive_packet(encoder->audio_avcc, output_packet);
193+
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
194+
break;
195+
} else if (response < 0) {
196+
logging("Error while receiving packet from encoder: %s", av_err2str(response));
197+
return -1;
198+
}
199+
200+
output_packet->stream_index = decoder->audio_index;
201+
202+
av_packet_rescale_ts(output_packet, decoder->audio_avs->time_base, encoder->audio_avs->time_base);
203+
response = av_interleaved_write_frame(encoder->avfc, output_packet);
204+
if (response != 0) { logging("Error %d while receiving packet from decoder: %s", response, av_err2str(response)); return -1;}
205+
}
206+
av_packet_unref(output_packet);
207+
av_packet_free(&output_packet);
208+
return 0;
209+
}
210+
211+
int transcode_audio(StreamingContext *decoder, StreamingContext *encoder, AVPacket *input_packet, AVFrame *input_frame) {
212+
int response = avcodec_send_packet(decoder->audio_avcc, input_packet);
213+
if (response < 0) {logging("Error while sending packet to decoder: %s", av_err2str(response)); return response;}
214+
215+
while (response >= 0) {
216+
response = avcodec_receive_frame(decoder->audio_avcc, input_frame);
217+
if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
218+
break;
219+
} else if (response < 0) {
220+
logging("Error while receiving frame from decoder: %s", av_err2str(response));
221+
return response;
222+
}
223+
224+
if (response >= 0) {
225+
if (encode_audio(decoder, encoder, input_frame)) return -1;
226+
}
227+
av_frame_unref(input_frame);
228+
}
229+
return 0;
230+
}
231+
152232
int transcode(StreamingContext *decoder, StreamingContext *encoder, AVPacket *input_packet, AVFrame *input_frame) {
153233
int response = avcodec_send_packet(decoder->video_avcc, input_packet);
154234
if (response < 0) {logging("Error while sending packet to decoder: %s", av_err2str(response)); return response;}
@@ -177,6 +257,7 @@ int main(int argc, char *argv[])
177257
sp.copy_video = 0;
178258
sp.fragmented_mp4 = 0;
179259
sp.video_codec = "x264";
260+
sp.audio_codec = "aac";
180261

181262
StreamingContext *decoder = (StreamingContext*) calloc(1, sizeof(StreamingContext));
182263
decoder->filename = argv[1];
@@ -198,7 +279,7 @@ int main(int argc, char *argv[])
198279
}
199280

200281
if (!sp.copy_audio) {
201-
// transcoding
282+
if (prepare_audio_encoder(encoder, decoder->audio_avcc->sample_rate, sp)) {return -1;}
202283
} else {
203284
if (prepare_copy(encoder->avfc, &encoder->audio_avs, decoder->audio_avs->codecpar)) {return -1;}
204285
}
@@ -238,7 +319,8 @@ int main(int argc, char *argv[])
238319
}
239320
} else if (decoder->avfc->streams[input_packet->stream_index]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
240321
if (!sp.copy_audio) {
241-
// TODO
322+
transcode_audio(decoder, encoder, input_packet, input_frame);
323+
av_packet_unref(input_packet);
242324
} else {
243325
if (remux(&input_packet, &encoder->avfc, decoder->audio_avs->time_base, encoder->audio_avs->time_base)) return -1;
244326
}

0 commit comments

Comments
 (0)