
Recherche avancée
Médias (1)
-
Video d’abeille en portrait
14 mai 2011, par
Mis à jour : Février 2012
Langue : français
Type : Video
Autres articles (111)
-
Le plugin : Podcasts.
14 juillet 2010, parLe problème du podcasting est à nouveau un problème révélateur de la normalisation des transports de données sur Internet.
Deux formats intéressants existent : Celui développé par Apple, très axé sur l’utilisation d’iTunes dont la SPEC est ici ; Le format "Media RSS Module" qui est plus "libre" notamment soutenu par Yahoo et le logiciel Miro ;
Types de fichiers supportés dans les flux
Le format d’Apple n’autorise que les formats suivants dans ses flux : .mp3 audio/mpeg .m4a audio/x-m4a .mp4 (...) -
Ajouter notes et légendes aux images
7 février 2011, parPour pouvoir ajouter notes et légendes aux images, la première étape est d’installer le plugin "Légendes".
Une fois le plugin activé, vous pouvez le configurer dans l’espace de configuration afin de modifier les droits de création / modification et de suppression des notes. Par défaut seuls les administrateurs du site peuvent ajouter des notes aux images.
Modification lors de l’ajout d’un média
Lors de l’ajout d’un média de type "image" un nouveau bouton apparait au dessus de la prévisualisation (...) -
MediaSPIP Init et Diogène : types de publications de MediaSPIP
11 novembre 2010, parÀ l’installation d’un site MediaSPIP, le plugin MediaSPIP Init réalise certaines opérations dont la principale consiste à créer quatre rubriques principales dans le site et de créer cinq templates de formulaire pour Diogène.
Ces quatre rubriques principales (aussi appelées secteurs) sont : Medias ; Sites ; Editos ; Actualités ;
Pour chacune de ces rubriques est créé un template de formulaire spécifique éponyme. Pour la rubrique "Medias" un second template "catégorie" est créé permettant d’ajouter (...)
Sur d’autres sites (5757)
-
Revision 33048 : Un flv n’a pas forcément de vidéo associée ... on écrit les metadatas ...
18 novembre 2009, par kent1@… — LogUn flv n’a pas forcément de vidéo associée ... on écrit les metadatas avant pour être sûr
-
C - Transcoding to UDP using FFmpeg ?
30 avril 2013, par golmschenkI'm trying to use the FFmpeg libraries to take an existing video file and stream it over a UDP connection. Specifically, I've been looking at the muxing.c and demuxing.c example files in the source code doc/example directory of FFmpeg. The demuxing file presents code which allows an input video to be converted into the video and audio streams. The muxing file presents code which creates fake data and can already be output to a UDP connection as I would like. I've begun work combining the two. Below can be found my code which is basically a copy of the muxing file with some parts replaced/appended with parts of the demuxing file. Unfortunately I'm running into plenty of complications attempting my goal through this approach. Is there an existing source code example which does the transcoding I'm looking for ? Or at least a tutorial on how one might create this ? If not, at least a few pointers might be helpful in directing my work in combing the two files to achieve my goal. Specifically, I'm getting the error :
[NULL @ 0x23b4040] Unable to find a suitable output format for 'udp://localhost:7777'
Could not deduce output format from file extension: using MPEG.
Output #0, mpeg, to 'udp://localhost:7777':Even though the muxing file could accept UDP formats. Any suggestions ? Thank you much !
#include
#include
#include
#include
#include <libavutil></libavutil>mathematics.h>
#include <libavformat></libavformat>avformat.h>
#include <libswscale></libswscale>swscale.h>
/* 5 seconds stream duration */
#define STREAM_DURATION 200.0
#define STREAM_FRAME_RATE 25 /* 25 images/s */
#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
//FROM DE
static AVFormatContext *fmt_ctx = NULL;
static AVCodecContext *video_dec_ctx = NULL, *audio_dec_ctx;
static AVStream *video_stream = NULL, *audio_stream = NULL;
static const char *src_filename = NULL;
static const char *video_dst_filename = NULL;
static const char *audio_dst_filename = NULL;
static FILE *video_dst_file = NULL;
static FILE *audio_dst_file = NULL;
static uint8_t *video_dst_data[4] = {NULL};
static int video_dst_linesize[4];
static int video_dst_bufsize;
static uint8_t **audio_dst_data = NULL;
static int audio_dst_linesize;
static int audio_dst_bufsize;
static int video_stream_idx = -1, audio_stream_idx = -1;
static AVFrame *frame = NULL;
static AVPacket pkt;
static int video_frame_count = 0;
static int audio_frame_count = 0;
//END DE
static int sws_flags = SWS_BICUBIC;
/**************************************************************/
/* audio output */
static float t, tincr, tincr2;
static int16_t *samples;
static int audio_input_frame_size;
/* Add an output stream. */
static AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,
enum AVCodecID codec_id)
{
AVCodecContext *c;
AVStream *st;
/* find the encoder */
*codec = avcodec_find_encoder(codec_id);
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",
avcodec_get_name(codec_id));
exit(1);
}
st = avformat_new_stream(oc, *codec);
if (!st) {
fprintf(stderr, "Could not allocate stream\n");
exit(1);
}
st->id = oc->nb_streams-1;
c = st->codec;
switch ((*codec)->type) {
case AVMEDIA_TYPE_AUDIO:
st->id = 1;
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->bit_rate = 64000;
c->sample_rate = 44100;
c->channels = 2;
break;
case AVMEDIA_TYPE_VIDEO:
c->codec_id = codec_id;
c->bit_rate = 400000;
/* Resolution must be a multiple of two. */
c->width = 352;
c->height = 288;
/* timebase: This is the fundamental unit of time (in seconds) in terms
* of which frame timestamps are represented. For fixed-fps content,
* timebase should be 1/framerate and timestamp increments should be
* identical to 1. */
c->time_base.den = STREAM_FRAME_RATE;
c->time_base.num = 1;
c->gop_size = 12; /* emit one intra frame every twelve frames at most */
c->pix_fmt = STREAM_PIX_FMT;
if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) {
/* just for testing, we also add B frames */
c->max_b_frames = 2;
}
if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) {
/* Needed to avoid using macroblocks in which some coeffs overflow.
* This does not happen with normal video, it just happens here as
* the motion of the chroma plane does not match the luma plane. */
c->mb_decision = 2;
}
break;
default:
break;
}
/* Some formats want stream headers to be separate. */
if (oc->oformat->flags & AVFMT_GLOBALHEADER)
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
return st;
}
/**************************************************************/
/* audio output */
static float t, tincr, tincr2;
static int16_t *samples;
static int audio_input_frame_size;
static void open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
AVCodecContext *c;
int ret;
c = st->codec;
/* open it */
ret = avcodec_open2(c, codec, NULL);
if (ret < 0) {
fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret));
exit(1);
}
/* init signal generator */
t = 0;
tincr = 2 * M_PI * 110.0 / c->sample_rate;
/* increment frequency by 110 Hz per second */
tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE)
audio_input_frame_size = 10000;
else
audio_input_frame_size = c->frame_size;
samples = av_malloc(audio_input_frame_size *
av_get_bytes_per_sample(c->sample_fmt) *
c->channels);
if (!samples) {
fprintf(stderr, "Could not allocate audio samples buffer\n");
exit(1);
}
}
/* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
* 'nb_channels' channels. */
static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
{
int j, i, v;
int16_t *q;
q = samples;
for (j = 0; j < frame_size; j++) {
v = (int)(sin(t) * 10000);
for (i = 0; i < nb_channels; i++)
*q++ = v;
t += tincr;
tincr += tincr2;
}
}
static void write_audio_frame(AVFormatContext *oc, AVStream *st)
{
AVCodecContext *c;
AVPacket pkt = { 0 }; // data and size must be 0;
AVFrame *frame = avcodec_alloc_frame();
int got_packet, ret;
av_init_packet(&pkt);
c = st->codec;
get_audio_frame(samples, audio_input_frame_size, c->channels);
frame->nb_samples = audio_input_frame_size;
avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt,
(uint8_t *)samples,
audio_input_frame_size *
av_get_bytes_per_sample(c->sample_fmt) *
c->channels, 1);
ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
if (ret < 0) {
fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
exit(1);
}
if (!got_packet)
return;
pkt.stream_index = st->index;
/* Write the compressed frame to the media file. */
ret = av_interleaved_write_frame(oc, &pkt);
if (ret != 0) {
fprintf(stderr, "Error while writing audio frame: %s\n",
av_err2str(ret));
exit(1);
}
avcodec_free_frame(&frame);
}
static void close_audio(AVFormatContext *oc, AVStream *st)
{
avcodec_close(st->codec);
av_free(samples);
}
/**************************************************************/
/* video output */
static AVFrame *frame;
static AVPicture src_picture, dst_picture;
static int frame_count;
static void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st)
{
int ret;
AVCodecContext *c = st->codec;
/* open the codec */
ret = avcodec_open2(c, codec, NULL);
if (ret < 0) {
fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret));
exit(1);
}
/* allocate and init a re-usable frame */
frame = avcodec_alloc_frame();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
/* Allocate the encoded raw picture. */
ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height);
if (ret < 0) {
fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret));
exit(1);
}
/* If the output format is not YUV420P, then a temporary YUV420P
* picture is needed too. It is then converted to the required
* output format. */
if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
ret = avpicture_alloc(&src_picture, AV_PIX_FMT_YUV420P, c->width, c->height);
if (ret < 0) {
fprintf(stderr, "Could not allocate temporary picture: %s\n",
av_err2str(ret));
exit(1);
}
}
/* copy data and linesize picture pointers to frame */
*((AVPicture *)frame) = dst_picture;
}
/* Prepare a dummy image. */
static void fill_yuv_image(AVPicture *pict, int frame_index,
int width, int height)
{
int x, y, i;
i = frame_index;
/* Y */
for (y = 0; y < height; y++)
for (x = 0; x < width; x++)
pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
/* Cb and Cr */
for (y = 0; y < height / 2; y++) {
for (x = 0; x < width / 2; x++) {
pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
}
}
}
static void write_video_frame(AVFormatContext *oc, AVStream *st)
{
int ret;
static struct SwsContext *sws_ctx;
AVCodecContext *c = st->codec;
if (frame_count >= STREAM_NB_FRAMES) {
/* No more frames to compress. The codec has a latency of a few
* frames if using B-frames, so we get the last frames by
* passing the same picture again. */
} else {
if (c->pix_fmt != AV_PIX_FMT_YUV420P) {
/* as we only generate a YUV420P picture, we must convert it
* to the codec pixel format if needed */
if (!sws_ctx) {
sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_YUV420P,
c->width, c->height, c->pix_fmt,
sws_flags, NULL, NULL, NULL);
if (!sws_ctx) {
fprintf(stderr,
"Could not initialize the conversion context\n");
exit(1);
}
}
fill_yuv_image(&src_picture, frame_count, c->width, c->height);
sws_scale(sws_ctx,
(const uint8_t * const *)src_picture.data, src_picture.linesize,
0, c->height, dst_picture.data, dst_picture.linesize);
} else {
fill_yuv_image(&dst_picture, frame_count, c->width, c->height);
}
}
if (oc->oformat->flags & AVFMT_RAWPICTURE) {
/* Raw video case - directly store the picture in the packet */
AVPacket pkt;
av_init_packet(&pkt);
pkt.flags |= AV_PKT_FLAG_KEY;
pkt.stream_index = st->index;
pkt.data = dst_picture.data[0];
pkt.size = sizeof(AVPicture);
ret = av_interleaved_write_frame(oc, &pkt);
} else {
AVPacket pkt = { 0 };
int got_packet;
av_init_packet(&pkt);
/* encode the image */
ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
if (ret < 0) {
fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
exit(1);
}
/* If size is zero, it means the image was buffered. */
if (!ret && got_packet && pkt.size) {
pkt.stream_index = st->index;
/* Write the compressed frame to the media file. */
ret = av_interleaved_write_frame(oc, &pkt);
} else {
ret = 0;
}
}
if (ret != 0) {
fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
exit(1);
}
frame_count++;
}
static void close_video(AVFormatContext *oc, AVStream *st)
{
avcodec_close(st->codec);
av_free(src_picture.data[0]);
av_free(dst_picture.data[0]);
av_free(frame);
}
static int open_codec_context(int *stream_idx,
AVFormatContext *fmt_ctx, enum AVMediaType type)
{
int ret;
AVStream *st;
AVCodecContext *dec_ctx = NULL;
AVCodec *dec = NULL;
ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
if (ret < 0) {
fprintf(stderr, "Could not find %s stream in input file '%s'\n",
av_get_media_type_string(type), src_filename);
return ret;
} else {
*stream_idx = ret;
st = fmt_ctx->streams[*stream_idx];
/* find decoder for the stream */
dec_ctx = st->codec;
dec = avcodec_find_decoder(dec_ctx->codec_id);
if (!dec) {
fprintf(stderr, "Failed to find %s codec\n",
av_get_media_type_string(type));
return ret;
}
if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
fprintf(stderr, "Failed to open %s codec\n",
av_get_media_type_string(type));
return ret;
}
}
return 0;
}
/**************************************************************/
/* media file output */
int main(int argc, char **argv)
{
const char *filename;
AVOutputFormat *fmt;
AVFormatContext *oc;
AVStream *audio_st, *video_st;
AVCodec *audio_codec, *video_codec;
double audio_pts, video_pts;
int ret = 0, got_frame;;
/* Initialize libavcodec, and register all codecs and formats. */
av_register_all();
if (argc != 3) {
printf("usage: %s input_file output_file\n"
"\n", argv[0]);
return 1;
}
src_filename = argv[1];
filename = argv[2];
/* allocate the output media context */
avformat_alloc_output_context2(&oc, NULL, NULL, filename);
if (!oc) {
printf("Could not deduce output format from file extension: using MPEG.\n");
avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
}
if (!oc) {
return 1;
}
fmt = oc->oformat;
/* Add the audio and video streams using the default format codecs
* and initialize the codecs. */
video_stream = NULL;
audio_stream = NULL;
//FROM DE
/* open input file, and allocate format context */
if (avformat_open_input(&fmt_ctx, src_filename, NULL, NULL) < 0) {
fprintf(stderr, "Could not open source file %s\n", src_filename);
exit(1);
}
/* retrieve stream information */
if (avformat_find_stream_info(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not find stream information\n");
exit(1);
}
if (open_codec_context(&video_stream_idx, fmt_ctx, AVMEDIA_TYPE_VIDEO) >= 0) {
video_stream = fmt_ctx->streams[video_stream_idx];
video_dec_ctx = video_stream->codec;
/* allocate image where the decoded image will be put */
ret = av_image_alloc(video_dst_data, video_dst_linesize,
video_dec_ctx->width, video_dec_ctx->height,
video_dec_ctx->pix_fmt, 1);
if (ret < 0) {
fprintf(stderr, "Could not allocate raw video buffer\n");
goto end;
}
video_dst_bufsize = ret;
}
if (open_codec_context(&audio_stream_idx, fmt_ctx, AVMEDIA_TYPE_AUDIO) >= 0) {
int nb_planes;
audio_stream = fmt_ctx->streams[audio_stream_idx];
audio_dec_ctx = audio_stream->codec;
nb_planes = av_sample_fmt_is_planar(audio_dec_ctx->sample_fmt) ?
audio_dec_ctx->channels : 1;
audio_dst_data = av_mallocz(sizeof(uint8_t *) * nb_planes);
if (!audio_dst_data) {
fprintf(stderr, "Could not allocate audio data buffers\n");
ret = AVERROR(ENOMEM);
goto end;
}
}
//END DE
/* Now that all the parameters are set, we can open the audio and
* video codecs and allocate the necessary encode buffers. */
if (video_stream)
open_video(oc, video_codec, video_stream);
if (audio_stream)
open_audio(oc, audio_codec, audio_stream);
av_dump_format(oc, 0, filename, 1);
/* open the output file, if needed */
if (!(fmt->flags & AVFMT_NOFILE)) {
ret = avio_open(&oc->pb, filename, AVIO_FLAG_WRITE);
if (ret < 0) {
fprintf(stderr, "Could not open '%s': %s\n", filename,
av_err2str(ret));
return 1;
}
}
/* Write the stream header, if any. */
ret = avformat_write_header(oc, NULL);
if (ret < 0) {
fprintf(stderr, "Error occurred when opening output file: %s\n",
av_err2str(ret));
return 1;
}
if (frame)
frame->pts = 0;
for (;;) {
/* Compute current audio and video time. */
if (audio_stream)
audio_pts = (double)audio_stream->pts.val * audio_stream->time_base.num / audio_stream->time_base.den;
else
audio_pts = 0.0;
if (video_stream)
video_pts = (double)video_stream->pts.val * video_stream->time_base.num /
video_stream->time_base.den;
else
video_pts = 0.0;
if ((!audio_stream || audio_pts >= STREAM_DURATION) &&
(!video_stream || video_pts >= STREAM_DURATION))
break;
/* write interleaved audio and video frames */
if (!video_stream || (video_stream && audio_st && audio_pts < video_pts)) {
write_audio_frame(oc, audio_stream);
} else {
write_video_frame(oc, video_stream);
frame->pts += av_rescale_q(1, video_stream->codec->time_base, video_stream->time_base);
}
}
/* Write the trailer, if any. The trailer must be written before you
* close the CodecContexts open when you wrote the header; otherwise
* av_write_trailer() may try to use memory that was freed on
* av_codec_close(). */
av_write_trailer(oc);
/* Close each codec. */
if (video_st)
close_video(oc, video_st);
if (audio_st)
close_audio(oc, audio_st);
if (!(fmt->flags & AVFMT_NOFILE))
/* Close the output file. */
avio_close(oc->pb);
/* free the stream */
avformat_free_context(oc);
end:
if (video_dec_ctx)
avcodec_close(video_dec_ctx);
if (audio_dec_ctx)
avcodec_close(audio_dec_ctx);
avformat_close_input(&fmt_ctx);
if (video_dst_file)
fclose(video_dst_file);
if (audio_dst_file)
fclose(audio_dst_file);
av_free(frame);
av_free(video_dst_data[0]);
av_free(audio_dst_data);
return 0;
} -
FFMPEG API -> Define input and output stream parameters using av_guess_codec()
11 septembre 2020, par bbddMy task is to save the raw
pcm_alaw
data to an audio file in Matroska format. Initially, I used this example to create an encoder, but I can't save the rawpcm_alaw
data correctly.

One of my colleagues recommended using the av_guess_codec() function to automatically detect the encoder. Also, he said that I would have to define parameters for the input and output stream, but I do not know how to do this.


What steps should I do to just write raw audio data in
pcm_alaw
format to a .mka audio file. The main goal is to record any raw data format in an.mka
audio file.

UPD Adding the code at the request of Hassaan Ali


audioGenerater.h



extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswresample/swresample.h"
}

class AudioGenerater
{
public:

 AudioGenerater(void);
 ~AudioGenerater(void);

 void generateAudioFile(
 QString fileName,
 QByteArray pcmData,
 int channel,
 int bitRate,
 int sampleRate,
 AVSampleFormat format);
private:

 bool initFormat(QString audioFileName);

private:

 AVCodec *m_AudioCodec = nullptr;
 AVCodecContext *m_AudioCodecContext = nullptr;
 AVFormatContext *m_FormatContext = nullptr;
 AVOutputFormat *m_OutputFormat = nullptr;
};




audioGenerater.cpp


AudioGenerater::AudioGenerater()
{
 av_register_all();
 avcodec_register_all();
}

bool AudioGenerater::initFormat(QString audioFileName)
{
 // Create an output Format context
 int result = avformat_alloc_output_context2(
 &m_FormatContext, nullptr, nullptr, audioFileName.toLocal8Bit().data());
 if (result < 0) {
 return false;
 }

 m_OutputFormat = m_FormatContext->oformat;

 // Create an audio stream
 AVStream *audioStream = avformat_new_stream(m_FormatContext, m_AudioCodec);
 if (audioStream == nullptr) {
 avformat_free_context(m_FormatContext);
 return false;
 }

 // Set the parameters in the stream for pcm_alaw (rtp payload type 8)
 audioStream->id = m_FormatContext->nb_streams - 1;
 audioStream->time_base = { 1, 8000 };
 result = avcodec_parameters_from_context(audioStream->codecpar, m_AudioCodecContext);
 if (result < 0) {
 avformat_free_context(m_FormatContext);
 return false;
 }

 // Print FormatContext information
 av_dump_format(m_FormatContext, 0, audioFileName.toLocal8Bit().data(), 1);

 // Open file IO
 if (!(m_OutputFormat->flags & AVFMT_NOFILE)) {
 result = avio_open(&m_FormatContext->pb, audioFileName.toLocal8Bit().data(), AVIO_FLAG_WRITE);
 if (result < 0) {
 avformat_free_context(m_FormatContext);
 return false;
 }
 }

 return true;
}

void AudioGenerater::generateAudioFile(
 QString _fileName,
 QByteArray _pcmData,
 int _channel,
 int _bitRate,
 int _sampleRate,
 AVSampleFormat _format)
{
 AVOutputFormat *fmt;
 /* allocate the output media context */
 AVFormatContext *oc;
 avformat_alloc_output_context2(&oc, NULL, NULL, _fileName.toStdString().c_str());
 if (!oc) {
 printf("Could not deduce output format from file extension: using mka.\n");
 avformat_alloc_output_context2(&oc, NULL, "mka", _fileName.toStdString().c_str());
 }
 if (!oc) {
 return;
 }
 fmt = oc->oformat;
 if (fmt->audio_codec == AV_CODEC_ID_NONE) {
 return;
 }
 
 AVCodecID codecID = av_guess_codec(fmt, "mka", _fileName.toStdString().c_str(), NULL, AVMEDIA_TYPE_AUDIO);
 // Find Codec
 m_AudioCodec = avcodec_find_encoder(codecID);
 if (m_AudioCodec == nullptr) {
 return;
 }

 // Create an encoder context
 m_AudioCodecContext = avcodec_alloc_context3(m_AudioCodec);
 if (m_AudioCodecContext == nullptr){
 return;
 }

 // Setting parameters
 m_AudioCodecContext->bit_rate = _bitRate;
 m_AudioCodecContext->sample_rate = _sampleRate;
 m_AudioCodecContext->sample_fmt = _format;
 m_AudioCodecContext->channels = _channel;


 m_AudioCodecContext->channel_layout = av_get_default_channel_layout(_channel);
 m_AudioCodecContext->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

 // Turn on the encoder
 int result = avcodec_open2(m_AudioCodecContext, m_AudioCodec, nullptr);
 if (result < 0) {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }

 // Create a package
 if (!initFormat(_fileName)) {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }

 // write to the file header
 result = avformat_write_header(m_FormatContext, nullptr);
 if (result < 0) {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }

 // Create Frame
 AVFrame *frame = av_frame_alloc();
 if (frame == nullptr) {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }

 int nb_samples = 0;
 if (m_AudioCodecContext->codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE) {
 nb_samples = 10000;
 }
 else {
 nb_samples = m_AudioCodecContext->frame_size;
 }

 // Set the parameters of the Frame
 frame->nb_samples = nb_samples;
 frame->format = m_AudioCodecContext->sample_fmt;
 frame->channel_layout = m_AudioCodecContext->channel_layout;

 // Apply for data memory
 result = av_frame_get_buffer(frame, 0);
 if (result < 0)
 {
 av_frame_free(&frame); {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }
 }

 // Set the Frame to be writable
 result = av_frame_make_writable(frame);
 if (result < 0)
 {
 av_frame_free(&frame); {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }
 }

 int perFrameDataSize = frame->linesize[0];
 int count = _pcmData.size() / perFrameDataSize;
 bool needAddOne = false;
 if (_pcmData.size() % perFrameDataSize != 0)
 {
 count++;
 needAddOne = true;
 }


 int frameCount = 0;
 for (int i = 0; i < count; ++i)
 {
 // Create a Packet
 AVPacket *pkt = av_packet_alloc();
 if (pkt == nullptr) {
 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
 return;
 }
 av_init_packet(pkt);

 if (i == count - 1)
 perFrameDataSize = _pcmData.size() % perFrameDataSize;

 // Synthesize WAV files
 memset(frame->data[0], 0, perFrameDataSize);
 memcpy(frame->data[0], &(_pcmData.data()[perFrameDataSize * i]), perFrameDataSize);

 frame->pts = frameCount++;
 // send Frame
 result = avcodec_send_frame(m_AudioCodecContext, frame);
 if (result < 0)
 continue;

 // Receive the encoded Packet
 result = avcodec_receive_packet(m_AudioCodecContext, pkt);
 if (result < 0)
 {
 av_packet_free(&pkt);
 continue;
 }

 // write to file
 av_packet_rescale_ts(pkt, m_AudioCodecContext->time_base, m_FormatContext->streams[0]->time_base);
 pkt->stream_index = 0;
 result = av_interleaved_write_frame(m_FormatContext, pkt);
 if (result < 0)
 continue;

 av_packet_free(&pkt);
 }

 // write to the end of the file
 av_write_trailer(m_FormatContext);
 // Close file IO
 avio_closep(&m_FormatContext->pb);
 // Release Frame memory
 av_frame_free(&frame);

 avcodec_free_context(&m_AudioCodecContext);
 if (m_FormatContext != nullptr)
 avformat_free_context(m_FormatContext);
}