I have written a routine that converts a file from one file format to
another - the code is very strongly based on output_example.c.  A
problem occurs the second time I attempt to encode a buffer that has
been read and decoded from the input file.  avcodec_encode_video always
returns -1.  This always happen on the second call - regardless of the
input file.  Can someone please explain what I am doing wrong?

The routine code is as follows:

        int frameFinished;
        AVFormatContext* pInputFormatCtx;
        AVFrame* pInputFrame;
        AVPacket inputPacket;
        AVCodec* pInputVideoCodec;
        AVCodecContext* pInputVideoCodecCtx;
        int inputVideoStreamPos = -1;
        uint8_t* pOutputBuffer;
        AVOutputFormat* pOutputFormat;
        AVFormatContext* pOutputFormatCtx;
        AVCodec* pOutputVideoCodec;
        AVCodecContext* pOutputVideoCodecCtx;
        AVStream* pOutputVideoStream;

        av_register_all();

        // Open the input file
 
      if (av_open_input_file(&pInputFormatCtx, pInput, NULL, 0,
NULL) != 0) return FileConverterEngine::UnableToOpenInputFile;
        try
        {
            // Get the stream information
            if (av_find_stream_info(pInputFormatCtx) < 0) return 
FileConverterEngine::UnableToRetrieveStreamInformation;
            for (unsigned int i=0; i < pInputFormatCtx->nb_streams; i++)
            {
                if (pInputFormatCtx->streams[i]->codec->codec_type == 
CODEC_TYPE_VIDEO)
                {
                    inputVideoStreamPos = i;
                    break;
                }
            }
            if (inputVideoStreamPos == -1) return 
FileConverterEngine::MissingVideoStream;

            // Get the codec context for the stream
            pInputVideoCodecCtx = 
pInputFormatCtx->streams[inputVideoStreamPos]->codec;

            // Get the codec to decode the video
            pInputVideoCodec = 
avcodec_find_decoder(pInputVideoCodecCtx->codec_id);
            if (pInputVideoCodec == NULL) return 
FileConverterEngine::UnableToFindVideoDecoder;

            // Open the codec
 
          if (avcodec_open(pInputVideoCodecCtx, pInputVideoCodec) <
0) return FileConverterEngine::UnableToOpenVideoDecoder;
            try
            {
                // What format is the output file?
                if ((pOutputFormat = guess_format(NULL, pOutput, NULL)) == NULL)
                {
 
                  if ((pOutputFormat = guess_format("mpeg", NULL,
NULL)) == NULL) return FileConverterEngine::CannotGuessOutputFormat;
                }

                // Allocate the output file context
 
              if ((pOutputFormatCtx = av_alloc_format_context()) ==
NULL) return FileConverterEngine::CannotAllocateOutputFileContext;
                try
                {
                    // Associate it with the output context
                    pOutputFormatCtx->oformat = pOutputFormat;

                    // Save the filename
                    _snprintf_s(pOutputFormatCtx->filename, 
sizeof(pOutputFormatCtx->filename), _TRUNCATE, "%s", pOutput);

                    // Add the video stream to the output file
                    if ((pOutputVideoStream = AddVideoStream(pOutputFormatCtx, 
pOutputFormat->video_codec)) == NULL)
                        return 
FileConverterEngine::CannotAddVideoStreamToOutputFile;

                    // Set-up the output video stream
                    pOutputVideoCodecCtx = pOutputVideoStream->codec;
                    pOutputVideoCodecCtx->width = pInputVideoCodecCtx->width;
                    pOutputVideoCodecCtx->height = pInputVideoCodecCtx->height;
                    pOutputVideoCodecCtx->pix_fmt = 
pInputVideoCodecCtx->pix_fmt;

                    // Set the output parameters
 
                  if (av_set_parameters(pOutputFormatCtx, NULL) < 0)
return FileConverterEngine::UnableToSetOutputParameters;

                    // Get the output video codec
                    if (!(pOutputVideoCodec = 
avcodec_find_encoder(pOutputVideoStream->codec->codec_id)))
                        return FileConverterEngine::UnableToFindVideoEncoder;

                    // Open the output video codec
 
                  if (avcodec_open(pOutputVideoCodecCtx,
pOutputVideoCodec) < 0) return
FileConverterEngine::UnableToOpenVideoEncoder;
                    try
                    {
                        // Open the output file (if needed)
                        if (!(pOutputFormat->flags & AVFMT_NOFILE))
                        {
 
                          if (url_fopen(&pOutputFormatCtx->pb,
pOutput, URL_WRONLY) < 0) return
FileConverterEngine::UnableToOpenOutputFile;
                        }
                        try
                        {
                            // Create the buffer to hold the encoded frame
 
                          int buffer_size =
avpicture_get_size(pOutputVideoCodecCtx->pix_fmt,
pOutputVideoCodecCtx->width, pOutputVideoCodecCtx->height);
                            pOutputBuffer = (uint8_t*)av_malloc(buffer_size);

                            // Write the headers to the output file
                            av_write_header(pOutputFormatCtx);

                            // Allocate the input frame
                            pInputFrame = avcodec_alloc_frame();
                            try
                            {
                                while (av_read_frame(pInputFormatCtx, 
&inputPacket) >= 0)
                                {
                                    if (inputPacket.stream_index == 
inputVideoStreamPos)
                                    {
                                        // Decode the video frame
 
                                      if
(avcodec_decode_video(pInputVideoCodecCtx, pInputFrame,
&frameFinished, inputPacket.data, inputPacket.size) < 0)
                                            return 
FileConverterEngine::UnableToDecodeInputVideoPacket;

                                        if (frameFinished)
                                        {

                                            // Encode the video frame (always 
returns -1 the second time this line is executed)
 
                                          int out_size =
avcodec_encode_video(pOutputVideoCodecCtx, pOutputBuffer, buffer_size,
pInputFrame);
                                        }

                                        // Free the packet
                                        av_free_packet(&inputPacket);
                                    }
                                }
                            }
                            finally
                            {
                                av_free(pInputFrame);
                            }

                            // Write the trailer
                            av_write_trailer(pOutputFormatCtx);
                        }
                        finally
                        {
                            if (!(pOutputFormat->flags & AVFMT_NOFILE))
                            {
                                url_fclose(pOutputFormatCtx->pb);
                            }
                        }
                    }
                    finally
                    {
                        avcodec_close(pOutputVideoCodecCtx);
                    }
                }
                finally
                {
                    av_free(pOutputFormatCtx);
                }
            }
            finally
            {
                avcodec_close(pInputVideoCodecCtx);
            }
        }
        finally
        {
            av_close_input_file(pInputFormatCtx);
        }



      
_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to