Hi,<div><br></div><div>I'm generating a video file from a collection of JPEG images, or rather trying to. I can generate a video, but it's not playable by any but the most forgiving of media players (e.g. mplayer, etc.). My problem seems to be with the way I'm trying to add images to the video. My encoding function is very similar to the video_encode_example() function from api-example.c in FFmpeg, except for the loop below.</div>
<div><br></div><div>Here's the main loop where I'm trying to add frames to the video. I tried passing the frame returned from open_image() to avcodec_encode_video(), but I get a -1 return value. I'm a bit stumped about how to encode a video that will be playable by most players. Any help would be greatly appreciated.</div>
<div><br></div><div> DIR *dir = opendir(path);</div><div><div> if (dir != NULL) {</div><div> </div><div> for(struct dirent *ent = readdir(dir); ent != NULL; ent = readdir(dir)) {</div><div> fflush(stdout);</div>
<div> </div><div> char filename[256];</div><div> sprintf(filename, "%s/%s", path, ent->d_name);</div><div> log(filename);</div><div> </div><div> const char * ext = strrchr(filename, '.');</div>
<div> if((!ext) || (strcmp(ext, ".jpg"))) {</div><div> continue;</div><div> }</div><div> </div><div> long bufSize = 0L;</div><div> AVFrame * frame = open_image(filename, width, height, &bufSize);</div>
<div> if(frame) {</div><div> //</div><div> // This hack works, but is obviously wrong</div><div> //</div><div> picture->data[0] = frame->data[0];</div>
<div> picture->data[1] = frame->data[1];</div><div> picture->data[2] = frame->data[2];</div><div> </div><div> picture->linesize[0] = frame->linesize[0];</div>
<div> picture->linesize[1] = frame->linesize[1];</div><div> picture->linesize[2] = frame->linesize[2];</div><div> </div><div> out_size = avcodec_encode_video(c, outbuf, outbuf_size, picture); </div>
<div> </div><div> log("encoding frame %3d (size=%5d)\n", i++, out_size);</div><div> </div><div> if(out_size < 0) {</div><div> log("Error encoding frame");</div>
<div> return -6;</div><div> }</div><div> </div><div> fwrite(outbuf, 1, out_size, f);</div><div><br></div><div> av_free(frame);</div><div> }</div>
<div> else {</div><div> log("Couldn't open image");</div><div> return -5;</div><div> }</div><div> }</div><div> </div><div> closedir(dir);</div>
<div> } </div><div> else {</div><div> log("Couldn't open directory");</div><div> return -4;</div><div> }</div></div><div><br></div><div>Here's my open_image() function:</div><div>
<br>
</div><div><div>AVFrame* open_image(const char* imageFileName, int width, int height, long * bufSize)</div><div>{</div><div> AVFormatContext *pFormatCtx;</div><div><br></div><div> if(av_open_input_file(&pFormatCtx, imageFileName, NULL, 0, NULL)!=0)</div>
<div> {</div><div> log("Can't open image file '%s'\n", imageFileName);</div><div> return NULL;</div><div> } </div><div><br></div><div> AVCodecContext *pCodecCtx = pFormatCtx->streams[0]->codec;</div>
<div> pCodecCtx->width = width;</div><div> pCodecCtx->height = height;</div><div> pCodecCtx->pix_fmt = PIX_FMT_YUV420P;</div><div><br></div><div> // Find the decoder for the video stream</div><div> AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);</div>
<div> if (!pCodec)</div><div> {</div><div> log("Codec not found");</div><div> return NULL;</div><div> }</div><div><br></div><div> // Open codec</div><div> if(avcodec_open(pCodecCtx, pCodec)<0)</div>
<div> {</div><div> log("Could not open codec");</div><div> return NULL;</div><div> }</div><div><br></div><div> AVFrame *pFrame = avcodec_alloc_frame();</div><div> if (!pFrame)</div><div>
{</div><div> log("Can't allocate memory for AVFrame\n");</div><div> return NULL;</div><div> }</div><div><br></div><div> int frameFinished;</div><div> int numBytes;</div><div><br></div>
<div> // Determine required buffer size and allocate buffer</div><div> numBytes = avpicture_get_size(PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);</div><div> </div><div> // ***</div><div> *bufSize = numBytes;</div>
<div> // ***</div><div> </div><div> uint8_t *buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));</div><div><br></div><div> avpicture_fill((AVPicture *) pFrame, buffer, PIX_FMT_YUVJ420P, pCodecCtx->width, pCodecCtx->height);</div>
<div><br></div><div> // Read frame</div><div><br></div><div> AVPacket packet;</div><div><br></div><div> int framesNumber = 0;</div><div> while (av_read_frame(pFormatCtx, &packet) >= 0)</div><div> {</div>
<div> if(packet.stream_index != 0)</div><div> continue;</div><div><br></div><div> int ret = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);</div><div> if (ret > 0)</div>
<div> {</div><div> pFrame->quality = 1;</div><div> return pFrame;</div><div> }</div><div> else {</div><div> log("Error [%d] while decoding frame: %s\n", ret, strerror(AVERROR(ret)));</div>
<div> }</div><div> }</div><div>}</div></div><div><br></div>