Hey there,<br><br>Before I start, I should point out that I have almost no expertise in audio and video codecs, and the same goes for ffmpeg/libav.<br>Also, I'm not used to mailing lists, so sorry if I'm doing something wrong related to that. :)<br>
<br>I'm trying to get all frames of an audio file (*.wav) and then save those frames to a new audio file with the same format (so a more or less copied file should be the result). This works well.<br><br>But now I'm trying to get all video frames of a file (*.mp4) that has both audio and video content. <br>
The getting seems to work fine without any errors.<br><br>But when trying to write the frames I got into a new video file with the same format - but this time, using video frames only, no audio - av_write_frame just crashes (always at same the frame interestingly) without giving any clue why. <br>
<br><br>Here is the function that reads the frames in:<br>//---------------------------------------------------------------------<br>
//---------------------------------------------------------------------<br>
//---------------------------------------------------------------------<br>void <br>FramesCollection::DecodeVideo(const char* p_filename)<br>{<br> av_log(NULL, AV_LOG_ERROR, "%s","Starting video decoding\n");<br>
<br> // Get the format context...<br> int ret = avformat_open_input(&_videoFormatContext, p_filename, NULL, NULL);<br> if (ret < 0)<br> {<br> av_log(NULL, AV_LOG_ERROR, "%s","Error opening file '%s'\n", p_filename);<br>
exit(-1);<br> }<br> // ... and fill it with stream info (contains number of frames, etc.)<br> av_find_stream_info(_videoFormatContext);<br><br> // Find the audio stream<br> AVStream* stream;<br> for(int i = 0; i < (int)_videoFormatContext->nb_streams; i++)<br>
{<br> if(_videoFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) <br> {<br> stream = _videoFormatContext->streams[i];<br> break;<br> }<br> }<br>
<br> // Use stream to set the context<br> _videoCodecContext = stream->codec;<br><br> // Find the codec<br> _videoCodec = avcodec_find_decoder(_videoCodecContext->codec_id);<br> if (!_videoCodec) <br>
{<br> av_log(_videoCodecContext, AV_LOG_ERROR, "%s","codec not found\n");<br> exit(-1);<br> }<br> // Open the codec<br> if (avcodec_open(_videoCodecContext, _videoCodec) < 0) <br>
{<br> av_log(_videoCodecContext, AV_LOG_ERROR, "%s","could not open codec\n");<br> exit(-1);<br> }<br><br> // Read each frame into a packet<br> AVPacket packet;<br> av_init_packet(&packet);<br>
int frameCount = 0;<br> while (av_read_frame(_videoFormatContext, &packet) == 0) <br> {<br> // Save the frame<br> AVPacket* tempPacket = new AVPacket(packet);<br> _videoPackets.push_back(tempPacket);<br>
} // END reading each frame<br> av_free_packet(&packet);<br>}<br><br><br>And here is the function that should write the new video:<br>//---------------------------------------------------------------------<br>
//---------------------------------------------------------------------<br>
//---------------------------------------------------------------------<br>void <br>FramesCollection::TestVideoEncode()<br>{<br> // Try writing<br> AVFormatContext* outputContext;<br> outputContext = avformat_alloc_context();<br>
outputContext->oformat = <br> av_guess_format(NULL, _videoFormatContext->filename, NULL);<br> char buffer[512];<br> sprintf(buffer, "C:\\test\\outTest.%s", outputContext->oformat->name);<br>
_snprintf_s(outputContext->filename, <br> sizeof(outputContext->filename), <br> strlen(buffer), <br> "%s", buffer);<br><br> // Add stream<br> if (!av_new_stream(outputContext, 0))<br>
{<br> av_log(outputContext, AV_LOG_ERROR, "%s","Error while creating stream.\n");<br> exit(-1);<br> }<br><br> // Open Codec<br> if (avcodec_open(outputContext->streams[0]->codec, _videoCodec) < 0)<br>
{<br> av_log(outputContext->streams[0]->codec, AV_LOG_ERROR, "%s","Error while opening codec for context.\n");<br> exit(-1);<br> }<br><br> // Set time base, dimensions, etc.<br>
outputContext->streams[0]->codec->time_base = _videoCodecContext->time_base;<br> outputContext->streams[0]->codec->width = _videoCodecContext->width;<br> outputContext->streams[0]->codec->height = _videoCodecContext->height;<br>
// Some container formats want stream headers to be global<br> if(outputContext->oformat->flags & AVFMT_GLOBALHEADER)<br> {<br> outputContext->streams[0]->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;<br>
}<br><br> // Open output file<br> if (url_fopen(&outputContext->pb, outputContext->filename, URL_WRONLY) < 0) <br> {<br> av_log(outputContext, <br> AV_LOG_ERROR, "%s","Could not open '%s'\n", outputContext->filename);<br>
exit(-1);<br> }<br><br> // Write Header<br> if (avformat_write_header(outputContext, NULL) < 0)<br> {<br> av_log(outputContext, AV_LOG_ERROR, "%s","Error while writing header.\n");<br>
exit(-1);<br> }<br><br> // Write each packet<br> for (int i = 0; i < (int)_videoPackets.size(); i++)<br> {<br> if (av_write_frame(outputContext, _videoPackets[i]) < 0)<br> {<br> av_log(outputContext, AV_LOG_ERROR, "%s","Error while writing frame.\n");<br>
exit(-1);<br> }<br> }<br><br> // Write trailer<br> if (av_write_trailer(outputContext) < 0)<br> {<br> av_log(outputContext, AV_LOG_ERROR, "%s","Error while writing trailer.\n");<br>
exit(-1);<br> }<br><br> // Close stuff<br> avcodec_close(outputContext->streams[0]->codec);<br> url_fclose(outputContext->pb);<br> avformat_free_context(outputContext);<br>}<br><br><br>As said, it always crashes at the same packet when trying to write them.<br>
Maybe I should also point out that the reading and writing of the audio frames is done in more or less identical functions.<br><br>
I have no clue... please help! :(<br>