2014-10-08 40 views
1

我一直試圖將字幕從格式SubRip(.srt)轉換爲MPEG4 Timed Text將它們複合到一個MP4容器,其中已經有音頻和視頻。在命令行與ffmpeg這樣做很簡單:錯誤打開解碼器與avcodec

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的(error.h從avutil)

+0

我已經確定了問題,** AVCodecContext **需要設置字幕標題。我不知道里面應該包含什麼,但是從** SRT **的編解碼環境中複製它似乎有訣竅 – marsop 2014-10-08 12:36:20

回答

0

錯誤代碼: 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片斷看到,是定義爲FFERRTAG('I','N','D','A')的AVERROR_INVALIDDATA。

錯誤代碼的其餘部分是在該文件中,我已經在這裏下面粘貼他們:

#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); 

很顯然,我沒有做字幕在這裏,但如果你要加載字幕把它們寫在如定時文本,這會讓你應該將它們裝入格式方面的意義。