के साथ ऑडियो और वीडियो फ़ाइलों से मुक्सिंग मैं सीख रहा हूं कि this उदाहरण से MP4 वीडियो कैसे बनाएं। समस्या यह है कि उदाहरण फ्लाई पर उत्पन्न कुछ डमी स्रोत डेटा से ऑडियो एन्कोडिंग प्रदर्शित करता है। मुझे फ़ाइल से ऑडियो एन्कोड करने की आवश्यकता है मैंने कई उदाहरणों की जांच की है और उनमें से अधिकतर एक ही या सिर्फ एक अलग ऑडियो एन्कोडिंग दिखाते हैं। मेरे परीक्षण और त्रुटि प्रक्रिया में मैं ऑडियो और वीडियो फ्रेम दोनों के लिए एक ही AVFormatContext का उपयोग कर रहा हूं। मुझे यकीन नहीं है कि यह सही काम है या मुझे 2 अलग-अलग संदर्भ हैं? अब तक मुझे वीडियो एन्कोडिंग ठीक है लेकिन ऑडियो स्ट्रीम विफल रहता है क्योंकि AVPacket सही ऑडियो स्ट्रीम इंडेक्स का पता नहीं लगा सकता है।FFmpeg
void open_audio(AVFormatContext *oc, AVCodec **codec, AVStream **st ,enum AVCodecID codec_id){
// AVCodecContext *c;
int ret;
// c = st->codec;
*codec = avcodec_find_encoder(codec_id);
if (!(*codec)) {
fprintf(stderr, "Could not find encoder for '%s'\n",avcodec_get_name(codec_id));
}
/* open it */
if(avformat_open_input(&oc,_audioInName.c_str(),NULL,NULL) !=0){
Msg::PrintErrorMsg("Error opening audio file");
}
AVStream* audioStream = NULL;
// Find the audio stream (some container files can have multiple streams in them)
for (uint32_t i = 0; i < oc->nb_streams; ++i)
{
if (oc->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
audioStream = oc->streams[i];
break;
}
}
if (audioStream == NULL)
{
Msg::PrintErrorMsg("Could not find any audio stream in the file");
}
*st =audioStream;
AVCodecContext *c = audioStream->codec;
c->codec = *codec;//avcodec_find_decoder(c->codec_id);
audioStream->id = 1;
c->sample_fmt = AV_SAMPLE_FMT_S16;
c->bit_rate = 64000;
c->sample_rate = 44100;
c->channels = 1;
if (oc->oformat->flags & AVFMT_GLOBALHEADER){
c->flags |= CODEC_FLAG_GLOBAL_HEADER;
}
if (c->codec == NULL)
{
Msg::PrintErrorMsg("Couldn't find a proper decoder");
}
ret = avcodec_open2(c, *codec, NULL);
if (ret < 0) {
Msg::PrintErrorMsg("Could not open audio codec\n");
}
}
यहाँ "OC" एक ही वीडियो स्ट्रीम प्रारंभ करने के रूप में अच्छी तरह से इस्तेमाल संदर्भ है: यहाँ कैसे मैं सेटअप ऑडियो स्ट्रीम है।
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);
////Read the packet:
while(av_read_frame(oc,&pkt) == 0){
if(pkt.stream_index ==st->index){
// Try to decode the packet into a frame
int frameFinished = 0;
avcodec_decode_audio4(c, frame, &frameFinished, &pkt);
// Some frames rely on multiple packets, so we have to make sure the frame is finished before
// we can use it
if (frameFinished){
assert(frameFinished);
ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
if (ret < 0) {
Msg::PrintErrorMsg("Error encoding audio frame\n");
}
if (!got_packet){
printf("failed to aquire packet");
}
pkt.stream_index = st->index;
/* Write the compressed frame to the media file. */
ret = av_interleaved_write_frame(oc, &pkt);
if (ret != 0) {
Msg::PrintErrorMsg("Error while writing audio frame.");
}
}
}
}
}
av_free_packet(&pkt);
avcodec_free_frame(&frame);
}
बात मैं कभी नहीं इस बयान से पारित किया गया है::। "अगर (pkt.stream_index == st-> सूचकांक)" पैकेट धारा सूचकांक है
तो मैं इस तरह ऑडियो फ्रेम लिखने के लिए कोशिश कर रहा हूँ ऑडियो स्ट्रीम इंडेक्स के बराबर कभी नहीं। कोई भी बता सकता है कि मैं कहां गलत हूं?
अद्यतन:
मैं एन्कोडिंग के लिए इनपुट ऑडियो स्ट्रीम को खोलने में कामयाब था, लेकिन मैं ऑडियो सांकेतिक शब्दों में बदलना नहीं कर सकते हैं और वीडियो एकल output.From में धाराओं मैं क्या देख सार्वजनिक टेलीफोन और डीटीएस शायद समस्या के स्रोत हैं वर्तमान में मैं muxing.c उदाहरण के आधार पर pts की गणना करता हूं लेकिन यह ऑडियो के लिए बिल्कुल काम नहीं करता है।
यहाँ कैसे मैं इसका उपयोग है: तो बुनियादी तौर पर मैं कर रहा हूँ
audio_pts = (double)audio_st->pts.val * audio_st->time_base.num/audio_st->time_base.den; is always zero because (double)audio_st->pts.val returns zero.
:
while(frame_count < _streamDurationNBFrames-1){
uint8_t *frameToWrite =_frames.front();
// Compute current audio and video time. ///
if (audio_st){
audio_pts = (double)audioIn_st->pts.val * audioIn_st->time_base.num/audioIn_st->time_base.den;
}
else{
audio_pts = 0.0;
}
if (video_st){
video_pts = (double)video_st->pts.val * video_st->time_base.num/ video_st->time_base.den;
}else{
video_pts = 0.0;
}
if ((!audio_st || audio_pts >= _streamDuration) && (!video_st || video_pts >= _streamDuration)){
break;
}
if (audio_st && audio_pts < video_pts) {
av_read_frame(informat, &pkt);//read audio from input stream
Msg::PrintMsg("Encode audio here...");
//================== AUDIO ENCODE HERE
outpkt.data = pkt.data;
outpkt.size = pkt.size;
outpkt.stream_index = pkt.stream_index;
outpkt.flags |= AV_PKT_FLAG_KEY;
outpkt.pts = pkt.pts;
outpkt.dts =pkt.dts;
if(av_interleaved_write_frame(oc, &outpkt) < 0)
{
Msg::PrintErrorMsg("Fail Audio Write ");
}
else
{
audio_st->codec->frame_number++;
}
av_free_packet(&outpkt);
av_free_packet(&pkt);
}else{
//================== VIDEO ENCODE HERE
write_video_frame(oc, video_st,frameToWrite);
frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);
}
///at last delete this frame:
_frames.pop();
delete frameToWrite; ///deallocate the written frame!
}
किसी तरह, एक बार मैं ऑडियो एन्कोडिंग पाश audio_pts video_pts कभी नहीं पहुँचता है और में हूँ हमेशा शून्य है एक ही प्रश्न फिर से पूछना: जब ऑडियो बाहरी फ़ाइल से आता है तो muxing कैसे करें?
बीटीडब्ल्यू, नीचे दिया गया जवाब मदद नहीं करता है क्योंकि यह लगता है कि ऑडियो और वीडियो स्ट्रीम दोनों एक ही फाइल से आते हैं, जबकि मेरे मामले में केवल ऑडियो बाहरी स्रोत से आता है।
मैं सेट अंक करते हैं, बस इसे नहीं डाल दिया है here.Yeah, मैं क्या जरूरत है जोड़ने के लिए है बनाया वीडियो के लिए ऑडियो मैं एन्कोडिंग कर रहा हूं। ऑडियो एएसी मीडिया फाइल से आता है। इस उदाहरण के लिए बहुत कुछ धन्यवाद, मैं इसे तब तक देखूंगा जब तक मैंने कोशिश की कुछ भी काम नहीं किया। –
क्या मुझे एन्कोडिंग से पहले avcodec_open2() के माध्यम से ऑडियो और वीडियो कोडेक्स नहीं खोलना चाहिए क्योंकि यह एफएफएमपीईजी उदाहरणों में दिखाया गया है? –
हाँ एन्कोडिंग के लिए आपको पहले avcodec_open2() को कॉल करने की आवश्यकता होगी। मेरे मामले में मैं सिर्फ स्ट्रीम कॉपी कर रहा था इसलिए मैंने इसका उपयोग नहीं किया। लेकिन आपको करने की ज़रूरत होगी। – praks411