Opened 10 years ago
Closed 10 years ago
#4404 closed defect (invalid)
Cannot decode PNG or TIF files with libavcodec.
Reported by: | sgan | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avcodec |
Version: | unspecified | Keywords: | PNG avcodec_decode_video2 |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
With libavcodec dlls, I cannot decode .PNG or .TIF files format but it is working fine with .JPEG or .BMP files.
Remark: with ffmpeg.exe, I am able to decode/encode these files (-i input.png -pix_fmt rgb32 output.bmp)
How to reproduce:
I am using latest dll provided by Zeranoe FFmpeg: Build Version: git-cf16b45 (2015-03-29) libavutil 54. 20.101 / 54. 20.101 libavcodec 56. 31.100 / 56. 31.100 libavformat 56. 26.101 / 56. 26.101 libavdevice 56. 4.100 / 56. 4.100 libavfilter 5. 13.101 / 5. 13.101 libswscale 3. 1.101 / 3. 1.101 libswresample 1. 1.100 / 1. 1.100 libpostproc 53. 3.100 / 53. 3.100 I am just testing the following code with a .png file: http://ffmpeg.org/doxygen/trunk/lavfutils_8c_source.html#l00024
Problem:
At line 77
ret = avcodec_decode_video2(codec_ctx, frame, &frame_decoded, &pkt);
ret is >0 and is equal to PNG file size, but frame_decoded=0!!
AVFrame *frame;
According to documentation:
http://ffmpeg.org/doxygen/trunk/group__lavc__decoding.html#ga99ee61b6dcffb7817a275d39da58cc74
"
- got_picture_ptr: Zero if no frame could be decompressed, otherwise, it is nonzero.
- Returns: On error a negative value is returned, otherwise the number of bytes used or zero if no frame could be decompressed."
In our case, we have at the same time :
- got_picture_ptr=0
- Returns=number of bytes used
It seems incompatible.
As said, the code is working fine with jpeg or bmp files.
Problem occurs on 32 or 64 bits dll.
Attachments (1)
Change History (4)
by , 10 years ago
Attachment: | 15x2Mire.png added |
---|
comment:1 by , 10 years ago
So I am still working on it and I think I finally found the solution.
As I am not an libavcodec expert, please fill free to comment.
According to avcodec_open2 documentation,
http://ffmpeg.org/doxygen/trunk/group__lavc__core.html#ga11f785a188d7d9df71621001465b0f1d
Prior to using this function the context has to be allocated with avcodec_alloc_context3().
So new code should be something like that (modifications have been commented as [sgan]:
int ff_load_image(uint8_t *data[4], int linesize[4], int *w, int *h, enum AVPixelFormat *pix_fmt, const char *filename, void *log_ctx) { AVInputFormat *iformat = NULL; AVFormatContext *format_ctx = NULL; AVCodec *codec; AVCodecContext *codec_ctx; AVFrame *frame; int frame_decoded, ret = 0; AVPacket pkt; av_init_packet(&pkt); av_register_all(); iformat = av_find_input_format("image2"); if ((ret = avformat_open_input(&format_ctx, filename, iformat, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Failed to open input file '%s'\n", filename); return ret; } if ((ret = avformat_find_stream_info(format_ctx, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Find stream info failed\n"); return ret; } //codec_ctx = format_ctx->streams[0]->codec; //[sgan]To remove codec = avcodec_find_decoder(codec_ctx->codec_id); //[sgan]To modify if (!codec) { av_log(log_ctx, AV_LOG_ERROR, "Failed to find codec\n"); ret = AVERROR(EINVAL); goto end; } codec_ctx = avcodec_alloc_context3(codec); //[sgan]To add if (!codec_ctx) return -1; //[sgan]To add codec_ctx->width=format_ctx->streams[0]->codec->width; //[sgan]To add codec_ctx->height=format_ctx->streams[0]->codec->height; //[sgan]To add codec_ctx->pix_fmt=format_ctx->streams[0]->codec->pix_fmt; //[sgan]To add if ((ret = avcodec_open2(codec_ctx, codec, NULL)) < 0) { av_log(log_ctx, AV_LOG_ERROR, "Failed to open codec\n"); goto end; } if (!(frame = av_frame_alloc()) ) { av_log(log_ctx, AV_LOG_ERROR, "Failed to alloc frame\n"); ret = AVERROR(ENOMEM); goto end; } ret = av_read_frame(format_ctx, &pkt); if (ret < 0) { av_log(log_ctx, AV_LOG_ERROR, "Failed to read frame from file\n"); goto end; } ret = avcodec_decode_video2(codec_ctx, frame, &frame_decoded, &pkt); if (ret < 0 || !frame_decoded) { av_log(log_ctx, AV_LOG_ERROR, "Failed to decode image from file\n"); if (ret >= 0) ret = -1; goto end; } *w = frame->width; *h = frame->height; *pix_fmt = frame->format; if ((ret = av_image_alloc(data, linesize, *w, *h, *pix_fmt, 16)) < 0) goto end; ret = 0; av_image_copy(data, linesize, (const uint8_t **)frame->data, frame->linesize, *pix_fmt, *w, *h); end: av_free_packet(&pkt); //avcodec_close(codec_ctx); //[sgan]To remove avcodec_free_context(&codec_ctx); //[sgan]To add avformat_close_input(&format_ctx); av_frame_free(&frame); if (ret < 0) av_log(log_ctx, AV_LOG_ERROR, "Error loading image file '%s'\n", filename); return ret; }
It seems that after:
codec_ctx = avcodec_alloc_context3(codec);
, some attibutes have to be set (width,height, ...).
Now it is working with PNG and TIFF files also.
comment:2 by , 10 years ago
I am following investigations!!
In fact, the original code http://ffmpeg.org/doxygen/trunk/lavfutils_8c_source.html#l00024 is working for PNG if we set the AVCodecContext::thread_count attribute to 1.
ex at line 59: format_ctx->streams[0]->codec->thread_count=1;
This is a workaround and I do not know why it is working. Problem should be analyse now deeply by developers.
The problem is connected to the following point:
http://stackoverflow.com/questions/22930109/call-to-avformat-find-stream-info-prevents-decoding-of-simple-png-image/22994263#22994263
Regards
Sebastien.
comment:3 by , 10 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
Yes, thread_count has to be set to 1 or the user application must call the decoder in a loop until the frame has been decoded.
Example of png file.