/** * encodes raw audio to various encodings like mp3 * @param args it holds various parameters like desired output encoding * @see libav_encode_args */ void audio_encode(libav_encode_args* a) { libav_encode_args& args = *a; avcodec_register_all(); AVCodec *codec; AVCodecContext *c = NULL; AVFrame *frame; AVPacket pkt; int i, j, k, ret, got_output; int max_input_buffer_size = args.input_buffer.periodbuffer->size(); int input_buffer_size = args.initptr < args.termptr ? (args.termptr - args. initptr + 1) : (args.termptr + args.input_buffer.periodbuffer-> size() - args.initptr + 1); FILE *f; uint16_t *samples; float t, tincr; // printf("Encode audio file %s\n", filename); /* find the MP2 encoder */ codec = avcodec_find_encoder(args.codecID); if (!codec) { // fprintf(stderr, "Codec not found\n"); // exit(1); ErrnoExit("Codec not found"); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = args.bitrate; /* check that the encoder supports s16 pcm input */ c->sample_fmt = args.av_smpl_fmt; //AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); c->channel_layout = select_channel_layout(codec); c->channels = av_get_channel_layout_nb_channels(c->channel_layout); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } // f = fopen(filename, "wb"); // if (!f) { // fprintf(stderr, "Could not open %s\n", filename); // exit(1); // } /* frame containing input raw audio */ frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; frame->channel_layout = c->channel_layout; /* the codec gives us the frame size, in samples, * we calculate the size of the samples buffer in bytes */ int computed_buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, c->sample_fmt, 0); samples = (uint16_t*) av_malloc(computed_buffer_size); if (!samples) { fprintf(stderr, "Could not allocate %d bytes for samples buffer\n", computed_buffer_size); exit(1); } /* setup the data pointers in the AVFrame */ if (computed_buffer_size != (*args.input_buffer.periodbuffer)[(args.initptr) % max_input_buffer_size].length) { fp_err(FPOL_LAV, "buffer statement mismatch. Encoder exited"); return; } ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (const uint8_t*) samples, computed_buffer_size, 0); if (ret < 0) { fprintf(stderr, "Could not setup audio frame\n"); exit(1); } /* encode a single tone sound */ // t = 0; //tincr = 2 * M_PI * 440.0 / c->sample_rate; args.output_buffer = (char*) malloc(input_buffer_size * (*args.input_buffer.periodbuffer)[(args.initptr) % max_input_buffer_size].length); args.output_buffer_size = 0; int non_cycled_termptr = args.initptr + input_buffer_size; for (i = args.initptr; i < non_cycled_termptr; i++) { av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; // for (j = 0; j < c->frame_size; j++) { // samples[2 * j] = (int) (sin(t) * 10000); // for (k = 1; k < c->channels; k++) { // samples[2 * j + k] = samples[2 * j]; // } // t += tincr; // } /* setup the data pointers in the AVFrame */ int k = 0; int l = computed_buffer_size / 4; uint16_t* obuffer = (uint16_t*) ((*args.input_buffer.periodbuffer)[i % max_input_buffer_size].period); for (j = 0; j < computed_buffer_size / 2; j++) { samples[k++] = obuffer[j]; j++; samples[l++] = obuffer[j]; } /* encode the samples */ ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding audio frame\n"); exit(1); } if (got_output) { //fwrite(pkt.data, 1, pkt.size, f); //pkt.data[pkt.size] = 0; memcpy(args.output_buffer + args.output_buffer_size, pkt.data, pkt.size); args.output_buffer_size += pkt.size; av_packet_unref(&pkt); } } /* get the delayed frames */ for (got_output = 1; got_output; i++) { ret = avcodec_encode_audio2(c, &pkt, NULL, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); exit(1); } if (got_output) { //fwrite(pkt.data, 1, pkt.size, f); memcpy(args.output_buffer + args.output_buffer_size, pkt.data, pkt.size); args.output_buffer_size += pkt.size; av_packet_unref(&pkt); } } // fclose(f); av_freep(&samples); av_frame_free(&frame); avcodec_close(c); av_free(c); }
/* * Audio encoding example */ static void audio_encode_example(const char *filename) { AVCodec *codec; AVCodecContext *c= NULL; AVFrame *frame; AVPacket pkt; int i, j, k, ret, got_output; int buffer_size; FILE *f; uint16_t *samples; float t, tincr; printf("Encode audio file %s\n", filename); /* find the MP2 encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_MP2); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = 64000; /* check that the encoder supports s16 pcm input */ c->sample_fmt = AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); c->channel_layout = select_channel_layout(codec); c->channels = av_get_channel_layout_nb_channels(c->channel_layout); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } /* frame containing input raw audio */ frame = avcodec_alloc_frame(); if (!frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; frame->channel_layout = c->channel_layout; /* the codec gives us the frame size, in samples, * we calculate the size of the samples buffer in bytes */ buffer_size = av_samples_get_buffer_size(NULL, c->channels, c->frame_size, c->sample_fmt, 0); samples = av_malloc(buffer_size); if (!samples) { fprintf(stderr, "Could not allocate %d bytes for samples buffer\n", buffer_size); exit(1); } /* setup the data pointers in the AVFrame */ ret = avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (const uint8_t*)samples, buffer_size, 0); if (ret < 0) { fprintf(stderr, "Could not setup audio frame\n"); exit(1); } /* encode a single tone sound */ t = 0; tincr = 2 * M_PI * 440.0 / c->sample_rate; for(i=0;i<200;i++) { av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; for (j = 0; j < c->frame_size; j++) { samples[2*j] = (int)(sin(t) * 10000); for (k = 1; k < c->channels; k++) samples[2*j + k] = samples[2*j]; t += tincr; } /* encode the samples */ ret = avcodec_encode_audio2(c, &pkt, frame, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding audio frame\n"); exit(1); } if (got_output) { fwrite(pkt.data, 1, pkt.size, f); av_free_packet(&pkt); } } /* get the delayed frames */ for (got_output = 1; got_output; i++) { ret = avcodec_encode_audio2(c, &pkt, NULL, &got_output); if (ret < 0) { fprintf(stderr, "Error encoding frame\n"); exit(1); } if (got_output) { fwrite(pkt.data, 1, pkt.size, f); av_free_packet(&pkt); } } fclose(f); av_freep(&samples); avcodec_free_frame(&frame); avcodec_close(c); av_free(c); }
int main(int argc, char **argv) { const char *filename; const AVCodec *codec; AVCodecContext *c = NULL; AVFrame *frame; AVPacket *pkt; int i, j, k, ret; FILE *f; uint16_t *samples; float t, tincr; if (argc <= 1) { fprintf(stderr, "Usage: %s <output file>\n", argv[0]); return 0; } filename = argv[1]; /* find the MP2 encoder */ codec = avcodec_find_encoder(AV_CODEC_ID_MP2); if (!codec) { fprintf(stderr, "Codec not found\n"); exit(1); } c = avcodec_alloc_context3(codec); if (!c) { fprintf(stderr, "Could not allocate audio codec context\n"); exit(1); } /* put sample parameters */ c->bit_rate = 64000; /* check that the encoder supports s16 pcm input */ c->sample_fmt = AV_SAMPLE_FMT_S16; if (!check_sample_fmt(codec, c->sample_fmt)) { fprintf(stderr, "Encoder does not support sample format %s", av_get_sample_fmt_name(c->sample_fmt)); exit(1); } /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); c->channel_layout = select_channel_layout(codec); c->channels = av_get_channel_layout_nb_channels(c->channel_layout); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { fprintf(stderr, "Could not open codec\n"); exit(1); } f = fopen(filename, "wb"); if (!f) { fprintf(stderr, "Could not open %s\n", filename); exit(1); } /* packet for holding encoded output */ pkt = av_packet_alloc(); if (!pkt) { fprintf(stderr, "could not allocate the packet\n"); exit(1); } /* frame containing input raw audio */ frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate audio frame\n"); exit(1); } frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; frame->channel_layout = c->channel_layout; /* allocate the data buffers */ ret = av_frame_get_buffer(frame, 0); if (ret < 0) { fprintf(stderr, "Could not allocate audio data buffers\n"); exit(1); } /* encode a single tone sound */ t = 0; tincr = 2 * M_PI * 440.0 / c->sample_rate; for (i = 0; i < 200; i++) { /* make sure the frame is writable -- makes a copy if the encoder * kept a reference internally */ ret = av_frame_make_writable(frame); if (ret < 0) exit(1); samples = (uint16_t*)frame->data[0]; for (j = 0; j < c->frame_size; j++) { samples[2 * j] = (int)(sin(t) * 10000); for (k = 1; k < c->channels; k++) samples[2 * j + k] = samples[2 * j]; t += tincr; } encode(c, frame, pkt, f); } /* flush the encoder */ encode(c, NULL, pkt, f); fclose(f); av_frame_free(&frame); av_packet_free(&pkt); avcodec_free_context(&c); return 0; }