2017-10-07 5 views
1

J'ai passé des heures à essayer de résoudre ce problème:FFmpeg api iOS "Ressource temporairement indisponible"

J'essaie d'utiliser l'API ffmpeg sur iOS. Mon projet Xcode se construit et je peux appeler les fonctions api ffmpeg. J'essaye d'écrire du code qui décode une vidéo (sans sortir quoi que ce soit pour l'instant), et je reçois toujours l'erreur -35: "Ressource temporairement indisponible".

Le fichier d'entrée provient de la pellicule (.mov) et j'utilise Mpeg-4 pour le décodage. Tout ce que je fais actuellement est d'obtenir des données à partir du fichier, en l'analysant et en envoyant les paquets analysés au décodeur. Quand j'essaie d'obtenir des images, tout ce que je reçois est une erreur. Est-ce que quelqu'un sait ce que je fais mal?

+(void)test: (NSString*)filename outfile:(NSString*)outfilename { 

/* register all the codecs */ 
avcodec_register_all(); 

AVCodec *codec; 
AVCodecParserContext *parser; 
AVCodecContext *c= NULL; 
int frame_count; 
FILE* f; 
AVFrame* frame; 
AVPacket* avpkt; 
avpkt = av_packet_alloc(); 
//av_init_packet(avpkt); 
char buf[1024]; 

uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE]; 
uint8_t *data; 
size_t data_size; 

/* set end of buffer to 0 (this ensures that no overreading happens for damaged mpeg streams) */ 
memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE); 

printf("Decode video file %s to %s\n", [filename cStringUsingEncoding:NSUTF8StringEncoding], [outfilename cStringUsingEncoding:NSUTF8StringEncoding]); 
/* find the h264 video decoder */ 
codec = avcodec_find_decoder(AV_CODEC_ID_MPEG4); 
if (!codec) { 
    fprintf(stderr, "Codec not found\n"); 
    exit(1); 
} 
c = avcodec_alloc_context3(codec); 
if (!c) { 
    fprintf(stderr, "Could not allocate video codec context\n"); 
    exit(1); 
} 
if (codec->capabilities & AV_CODEC_CAP_TRUNCATED) 
    c->flags |= AV_CODEC_FLAG_TRUNCATED; // we do not send complete frames 
/* For some codecs, such as msmpeg4 and mpeg4, width and height 
MUST be initialized there because this information is not 
available in the bitstream. */ 
/* open it */ 
if (avcodec_open2(c, codec, NULL) < 0) { 
    fprintf(stderr, "Could not open codec\n"); 
    exit(1); 
} 
f = fopen([filename cStringUsingEncoding:NSUTF8StringEncoding], "rb"); 
if (!f) { 
    fprintf(stderr, "Could not open %s\n", [filename cStringUsingEncoding:NSUTF8StringEncoding]); 
    exit(1); 
} 
frame = av_frame_alloc(); 
if (!frame) { 
    fprintf(stderr, "Could not allocate video frame\n"); 
    exit(1); 
} 
frame_count = 0; 

parser = av_parser_init(codec->id); 
if (!parser) { 
    fprintf(stderr, "parser not found\n"); 
    exit(1); 
} 

while (!feof(f)) { 
    /* read raw data from the input file */ 
    data_size = fread(inbuf, 1, INBUF_SIZE, f); 
    if (!data_size) 
     break; 
    /* use the parser to split the data into frames */ 
    data = inbuf; 
    while (data_size > 0) { 
     int ret = av_parser_parse2(parser, c, &avpkt->data, &avpkt->size, data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); 
     if (ret < 0) { 
      fprintf(stderr, "Error while parsing\n"); 
      exit(1); 
     } 
     data  += ret; 
     data_size -= ret; 
     if (avpkt->size){ 
      char buf[1024]; 

      ret = avcodec_send_packet(c, avpkt); 
      if (ret < 0) { 

       fprintf(stderr, "Error sending a packet for decoding\n"); 
       continue; 
       exit(1); 
      } 

      while (ret >= 0) { 
       ret = avcodec_receive_frame(c, frame); 
       if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){ 
        char e [1024]; 
        av_strerror(ret, e, 1024); 
        fprintf(stderr, "Fail: %s !\n", e); 
// ~~~~~~~~ This is where my program exits ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
        return; 
       } 
       else if (ret < 0) { 
        fprintf(stderr, "Error during decoding\n"); 
        exit(1); 
       } 
      } 


     } 
    } 
} 
/* some codecs, such as MPEG, transmit the I and P frame with a 
latency of one frame. You must do the following to have a 
chance to get the last frame of the video */ 

fclose(f); 
avcodec_close(c); 
av_free(c); 
av_frame_free(&frame); 
printf("\n"); 

}

Répondre

3

AVERROR(EAGAIN) est pas une erreur, cela signifie juste que la sortie ne sont pas encore disponibles et vous devez appeler _send_packet() quelques fois avant la première sortie sera disponible à partir _receive_frame().

La sortie est mise en mémoire tampon (retardée) pour permettre les trames B et le filetage de trame.