video - 使用 avcodec 打开编解码器时出错

标签 video encoding ffmpeg libavcodec avcodec

我一直在尝试从格式 SubRip 转码字幕(.srt) 到 MPEG4 Timed Text将它们混合到一个 MP4 容器中,其中已经有音频和视频。使用 ffmpeg 从命令行执行此操作微不足道:

ffmpeg -i subtitles.srt -i video.mp4 -c:v copy -c:a copy -c:s mov_text videoWithSubtitles.mp4

但是,使用 avcodec,我可以打开这两个文件并从中读取,但是当我尝试打开 AVCodecContext 对于(编码器)编解码器AV_CODEC_ID_MOV_TEXT ,我收到以下消息:
Error code: -1094995529
Error occurred: Invalid data found when processing input

产生错误的代码如下:
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_MOV_TEXT);
if (!codec) {
    NSLog(@"Error finding encoder");
    exit(-1);
}

AVCodecContext *codecContext = avcodec_alloc_context3(codec);
if (!codecContext) {
    NSLog(@"Error allocating context");
    exit(-1);
}

if (avcodec_is_open(codecContext) == 0) {
    NSLog(@"output codec context is closed, opening");
    ret = avcodec_open2(codecContext, codec, NULL);
    if (ret < 0) {
        NSLog(@"Error code: %i",ret);
        NSLog(@"Error occurred: %s", av_err2str(ret));
        NSLog(@"Error opening encoder");
        exit(-1);
    }
}

该代码适用于所有解码器(相同的编解码器在解码模式下工作)以及其他编码器,主要是视频或音频,但它也不适用于 AV_CODEC_ID_SUBRIPAV_CODEC_ID_SRT (设置编码器)。

最佳答案

来自 ffmpeg 的错误代码(来自 avutil 的 error.h):
http://ffmpeg.org/doxygen/trunk/error_8h_source.html

原来您指定的值是:

#define AVERROR_INVALIDDATA        FFERRTAG( 'I','N','D','A')

-1094995529 变为 -0x41444E49,当您查看这些字母时,在 ACSII 中,0x41 = 'A'、0x44 = 'D'、0x4E = 'N 和 0x49 = 'I'。由于宏/等事情是相反的,所以ADNI变成了INDA,你可以从#define片段中看到,是AVERROR_INVALIDDATA定义的FFERRTAG('I','N','D','A')。

其余的错误代码在该文件中,我已将它们粘贴在下面:
#define AVERROR_BSF_NOT_FOUND      FFERRTAG(0xF8,'B','S','F') ///< Bitstream filter not found
#define AVERROR_BUG                FFERRTAG( 'B','U','G','!') ///< Internal bug, also see AVERROR_BUG2
#define AVERROR_BUFFER_TOO_SMALL   FFERRTAG( 'B','U','F','S') ///< Buffer too small
#define AVERROR_DECODER_NOT_FOUND  FFERRTAG(0xF8,'D','E','C') ///< Decoder not found
#define AVERROR_DEMUXER_NOT_FOUND  FFERRTAG(0xF8,'D','E','M') ///< Demuxer not found
#define AVERROR_ENCODER_NOT_FOUND  FFERRTAG(0xF8,'E','N','C') ///< Encoder not found
#define AVERROR_EOF                FFERRTAG( 'E','O','F',' ') ///< End of file
#define AVERROR_EXIT               FFERRTAG( 'E','X','I','T') ///< Immediate exit was requested; the called function should not be restarted
#define AVERROR_EXTERNAL           FFERRTAG( 'E','X','T',' ') ///< Generic error in an external library
#define AVERROR_FILTER_NOT_FOUND   FFERRTAG(0xF8,'F','I','L') ///< Filter not found
#define AVERROR_INVALIDDATA        FFERRTAG( 'I','N','D','A') ///< Invalid data found when processing input
#define AVERROR_MUXER_NOT_FOUND    FFERRTAG(0xF8,'M','U','X') ///< Muxer not found
#define AVERROR_OPTION_NOT_FOUND   FFERRTAG(0xF8,'O','P','T') ///< Option not found
#define AVERROR_PATCHWELCOME       FFERRTAG( 'P','A','W','E') ///< Not yet implemented in FFmpeg, patches welcome
#define AVERROR_PROTOCOL_NOT_FOUND FFERRTAG(0xF8,'P','R','O') ///< Protocol not found
#define AVERROR_STREAM_NOT_FOUND   FFERRTAG(0xF8,'S','T','R') ///< Stream not found
#define AVERROR_BUG2               FFERRTAG( 'B','U','G',' ')
#define AVERROR_UNKNOWN            FFERRTAG( 'U','N','K','N') ///< Unknown error, typically from an external library
#define AVERROR_EXPERIMENTAL       (-0x2bb2afa8) ///< Requested feature is flagged experimental. Set strict_std_compliance if you really want to use it.
#define AVERROR_INPUT_CHANGED      (-0x636e6701) ///< Input changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_OUTPUT_CHANGED)
#define AVERROR_OUTPUT_CHANGED     (-0x636e6702) ///< Output changed between calls. Reconfiguration is required. (can be OR-ed with AVERROR_INPUT_CHANGED)
#define AVERROR_HTTP_BAD_REQUEST   FFERRTAG(0xF8,'4','0','0')
#define AVERROR_HTTP_UNAUTHORIZED  FFERRTAG(0xF8,'4','0','1')
#define AVERROR_HTTP_FORBIDDEN     FFERRTAG(0xF8,'4','0','3')
#define AVERROR_HTTP_NOT_FOUND     FFERRTAG(0xF8,'4','0','4')
#define AVERROR_HTTP_OTHER_4XX     FFERRTAG(0xF8,'4','X','X')
#define AVERROR_HTTP_SERVER_ERROR  FFERRTAG(0xF8,'5','X','X')

AVFormatContext 很棘手。我最终得到了我的工作,但我确信我做了很多额外的副本和疯狂的事情。
av_register_all();
avformat_network_init();

//Allocate space and setup the the object to be used for storing 
// all info needed for this connection
context = avformat_alloc_context();

AVDictionary *opts = 0;
av_dict_set(&opts, "rtsp_transport", "tcp", 0);

//open rtsp
if (avformat_open_input(&context, URL, NULL, &opts) != 0){
    return 1; //Error 1
}

//maximum time in microseconds during which the input should be analyzed
context->max_analyze_duration = 10000000;

if (avformat_find_stream_info(context,NULL) < 0){
    return 2; //Error 2
}

//search video stream
for(int i=0; i<(int)context->nb_streams; i++){
    if(context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        video_stream_index = i;
}

oc = avformat_alloc_context();

//start reading packets from stream and write them to file
av_read_play(context);  //start the stream

if(curVidFormat == MJPEG) {
    codec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
}
else {
    codec = avcodec_find_decoder(AV_CODEC_ID_H264);
}

if (!codec) return 3; //Error 3
ccontext = avcodec_alloc_context3(codec);    

avcodec_get_context_defaults3(ccontext, codec);
avcodec_copy_context(ccontext,context->streams[video_stream_index]->codec);

int errorCode = avcodec_open2(ccontext, codec, NULL);
if(errorCode<0)
{
    printf("avcodec_open2 failed with errorCode:%d !",errorCode);
    exit(1);
}

//create frame to be used for storing frames coming out 
// of avcodec_decode_video2
int curAVFramesize = avpicture_get_size(PIX_FMT_YUV420P, 
     ccontext->width, ccontext->height);
curAVFramePicBuffer = (uint8_t*)(av_malloc(curAVFramesize));
curAVFrame=avcodec_alloc_frame();
avpicture_fill((AVPicture *)curAVFrame,curAVFramePicBuffer,
     PIX_FMT_YUV420P,ccontext->width, ccontext->height);
returnAVFramesize = avpicture_get_size(PIX_FMT_YUV420P, ccontext->width, ccontext->height);

//allocate and create frame to be used for resizing of frames
int resizedFramesize = avpicture_get_size(PIX_FMT_YUV420P, outputWidth,
    outputHeight);
resizedFramePicBuffer = (uint8_t*)(av_malloc(resizedFramesize));
resizedFrame=avcodec_alloc_frame();
avpicture_fill((AVPicture *)resizedFrame,resizedFramePicBuffer,
    PIX_FMT_YUV420P,outputWidth, outputHeight);

//Could be used to convert between formats
//In this case just scaling the image
img_convert_ctx = sws_getContext(ccontext->width, ccontext->height,
     ccontext->pix_fmt, width, height, PIX_FMT_YUV420P, 
     SWS_BICUBIC, NULL, NULL, NULL);

显然我在这里不做字幕,但是如果您尝试加载字幕以将它们作为定时文本写入,那么您应该将它们加载到格式上下文中是有意义的。

关于video - 使用 avcodec 打开编解码器时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26252888/

相关文章:

html - NodeJS - 如何将相同的视频流传输到多个客户端?

video - 无法使用ffmpeg更改视频字幕编解码器

c# - 如何将 UTF-8 阿拉伯字母转换为 CodePage 1001?

java - 在 idea intellij 中更改编码不起作用

ffmpeg - 无损RGB24到YUV444转换

video - 使用单个命令加速和倒转视频?

ios - 上传视频并分享链接 - API?

encoding - 使用 FFMPEG 进行 H.264 编码 - 某些视频无法正常工作

c++ - 如何将视频级别分配给ffmpeg中的结构AVCodecContext?

video - m3u8 文件中的随机 .ts 文件名