2010-07-26 4 views
4

Я пытаюсь кодировать серии изображений в один видеофайл. Я использую код из api-example.c, его работы, но он дает мне странные зеленые цвета в видео. Я знаю, мне нужно, чтобы преобразовать мой RGB изображение в формате YUV, я нашел решение, но его не делает работу, цвета не зеленый, но очень странно, так то будет код:Кодирование изображений в видео с помощью ffmpeg

// Register all formats and codecs 
    av_register_all(); 

    AVCodec *codec; 
    AVCodecContext *c= NULL; 
    int i, out_size, size, outbuf_size; 
    FILE *f; 
    AVFrame *picture; 
    uint8_t *outbuf; 

    printf("Video encoding\n"); 

    /* find the mpeg video encoder */ 
    codec = avcodec_find_encoder(CODEC_ID_MPEG2VIDEO); 
    if (!codec) { 
     fprintf(stderr, "codec not found\n"); 
     exit(1); 
    } 

    c= avcodec_alloc_context(); 
    picture= avcodec_alloc_frame(); 

    /* put sample parameters */ 
    c->bit_rate = 400000; 
    /* resolution must be a multiple of two */ 
    c->width = 352; 
    c->height = 288; 
    /* frames per second */ 
    c->time_base= (AVRational){1,25}; 
    c->gop_size = 10; /* emit one intra frame every ten frames */ 
    c->max_b_frames=1; 
    c->pix_fmt = PIX_FMT_YUV420P; 

    /* open it */ 
    if (avcodec_open(c, codec) < 0) { 
     fprintf(stderr, "could not open codec\n"); 
     exit(1); 
    } 

    f = fopen(filename, "wb"); 
    if (!f) { 
     fprintf(stderr, "could not open %s\n", filename); 
     exit(1); 
    } 

    /* alloc image and output buffer */ 
    outbuf_size = 100000; 
    outbuf = malloc(outbuf_size); 
    size = c->width * c->height; 

#pragma mark - 
    AVFrame* outpic = avcodec_alloc_frame(); 
    int nbytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height); 

    //create buffer for the output image 
    uint8_t* outbuffer = (uint8_t*)av_malloc(nbytes); 

#pragma mark - 
    for(i=1;i<77;i++) { 
     fflush(stdout); 

     int numBytes = avpicture_get_size(PIX_FMT_YUV420P, c->width, c->height); 
     uint8_t *buffer = (uint8_t *)av_malloc(numBytes*sizeof(uint8_t)); 

     UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"10%d", i]]; 
     CGImageRef newCgImage = [image CGImage]; 

     CGDataProviderRef dataProvider = CGImageGetDataProvider(newCgImage); 
     CFDataRef bitmapData = CGDataProviderCopyData(dataProvider); 
     buffer = (uint8_t *)CFDataGetBytePtr(bitmapData); 

     avpicture_fill((AVPicture*)picture, buffer, PIX_FMT_RGB8, c->width, c->height); 
     avpicture_fill((AVPicture*)outpic, outbuffer, PIX_FMT_YUV420P, c->width, c->height); 

     struct SwsContext* fooContext = sws_getContext(c->width, c->height, 
               PIX_FMT_RGB8, 
               c->width, c->height, 
               PIX_FMT_YUV420P, 
               SWS_FAST_BILINEAR, NULL, NULL, NULL); 

     //perform the conversion 
     sws_scale(fooContext, picture->data, picture->linesize, 0, c->height, outpic->data, outpic->linesize); 
     // Here is where I try to convert to YUV 

     /* encode the image */ 
     out_size = avcodec_encode_video(c, outbuf, outbuf_size, outpic); 
     printf("encoding frame %3d (size=%5d)\n", i, out_size); 
     fwrite(outbuf, 1, out_size, f); 

     free(buffer); 
     buffer = NULL;  

    } 

    /* get the delayed frames */ 
    for(; out_size; i++) { 
     fflush(stdout); 

     out_size = avcodec_encode_video(c, outbuf, outbuf_size, NULL); 
     printf("write frame %3d (size=%5d)\n", i, out_size); 
     fwrite(outbuf, 1, outbuf_size, f);  
    } 

    /* add sequence end code to have a real mpeg file */ 
    outbuf[0] = 0x00; 
    outbuf[1] = 0x00; 
    outbuf[2] = 0x01; 
    outbuf[3] = 0xb7; 
    fwrite(outbuf, 1, 4, f); 
    fclose(f); 
    free(outbuf); 

    avcodec_close(c); 
    av_free(c); 
    av_free(picture); 
    printf("\n"); 

Пожалуйста, дайте мне совет как исправить эту проблему.

+0

1 вопрос. Какая структура требует кода выше? – aryaxt

+0

Для этого требуется библиотека FFmpeg http://www.ffmpeg.org/. – Steve

+0

Я тоже сталкиваюсь с той же проблемой ... Не могли бы вы помочь мне с вашим решением .... – Ganesh

ответ

0

Я думаю, что проблема в том, что вы используете PIX_FMT_RGB8 в качестве формата входного пикселя. Это не означает 8 бит на канал, как обычно используемый 24-разрядный RGB или 32-разрядный ARGB. Это означает 8 бит на пиксель, что означает, что все три цветовых канала помещаются в один байт. Я предполагаю, что это не формат вашего изображения, так как это довольно необычно, поэтому вам нужно использовать PIX_FMT_RGB24 или PIX_FMT_RGB32 в зависимости от того, имеет ли ваше входное изображение альфа-канал. См. Страницу this documentation для получения информации о форматах пикселей.

+0

Спасибо. Я попробовал PIX_FMT_RGB24 и PIX_FMT_RGB32 и многие другие. Я использовал PIX_FMT_RGB8, потому что мои изображения были оптимизированы для сети, индексированные 8-битные цвета pngs и другие материалы для фотошоп, чтобы сделать их меньше. Но я пробовал другие изображения в обычных форматах, просто чтобы проверить, с различными вариантами PIX_FMT, это все равно дает мне неправильный результат, поэтому я думаю, что проблема в коде. – Steve

+0

Вы попробовали PIX_FMT_PAL8? Этот формат предназначен для 8-битного индексированного цвета. С PIX_FMT_PAL8 цветовая палитра должна быть отправлена ​​вместе с фреймом. Эта страница документации, с которой я связан, рассказывает об этом прямо перед определением всех форматов пикселей. В нем говорится, что AVFrame.data [0] содержит индексы в палитре для каждого пикселя, в то время как AVFrame.data [1] содержит 1024-байтовый массив, определяющий фактические значения цвета ARGB для каждого 8-битного индекса. –

1

Кто-нибудь нашел исправление для этого? Я вижу проблему зеленого видео на стороне декодирования. То есть, когда я декодирую входящие пакеты PIX_FMT_YUV420, а затем swsscale их в PIX_FMT_RGBA.

Спасибо!

РЕДАКТИРОВАТЬ: Зеленые изображения, вероятно, связаны с оптимизацией руки. Я использовал это, чтобы решить эту проблему в моем случае: http://ffmpeg-users.933282.n4.nabble.com/green-distorded-output-image-on-iPhone-td2231805.html

Я предполагаю, что идея заключается в том, чтобы не указать любую архитектуру (конфиг будет Вам предупреждение о архитектуре неизвестности, но вы можете продолжать «делать» в любом случае). Таким образом, оптимизация руки не используется. Там может быть небольшой удар производительности (если есть), но по крайней мере он работает! :)

Смежные вопросы