Reputation: 3073
Following the exmaples of ffmpeg: decoding_encoding.c and filtering_video.c, I process one video file taken by iPhone. The video file: .mov, video dimensions; 480x272, video Codec: H.264/AVC, 30 frames per second, bitrate: 605 kbps.
I first extract each frame, which is YUV. I convert YUV to RGB24, and process the RGB24, then write the RGB24 to a .ppm file. It shows the .ppm file is correct.
Then I plan to encode processed RGB24 frames to a video file. Since MPEG does not support RGB24 picture format, I used AV_CODEC_ID_HUFFYUV. But the output video file (showing 18.5 MB) does not play. Movie Player on Ubuntu claims an error: Could not determine type of stream. I also tried it on VCL. It simply does not work, without any error information.
My second questions is: For each extracted fram from the input video file, I get its pts as follows according to filtering_video.c:
frame->pts = av_frame_get_best_effort_timestamp(frame);
I print out each frame's pts, and find that it increases by 20, like below:
pFrameRGB_count: 0, frame->pts: 0
pFrameRGB_count: 1, frame->pts: 20
pFrameRGB_count: 2, frame->pts: 40
pFrameRGB_count: 3, frame->pts: 60
Where frame is the extracted frame from the input video, and pFrameRGB_count is the count for processed frame in RGB24 form.
Why are they wrong?
Upvotes: 7
Views: 3721
Reputation: 3073
I think I find the answer. Due to lack of detailed documentation of ffmpeg, users might be mislead. I find that, to get correct pts, one should always use: video_st->time_base NOT video_st->codec->time_base
(a) Absolute time of a frame:
packet->dts * (1/video_st->time_base.den)
(b) Absolute time between the frame and its next frame:
frame->repeat_pict * (1/video_st->time_base.den)
Upvotes: 0
Reputation: 3073
I debug to get codec context of the input video file, dec_ctx->time_base.den = 1200; I know the fps, 30, by right-click the input video file to check its properties (Ubuntu 12.04) So it seems the frame duration should be 1200/30 = 40 base units. But it is 20 by using frame->pts = av_frame_get_best_effort_timestamp(frame);
the read packet of the input video has the duration = 20.
I found dec_ctx->ticks_per_frame = 2. I guess ticks_per_frame makes 40 to 20. Maybe there is some inner formula, like: frame duration in base unit = frame duration x ticks_per_frame (but it seems it is different from what is said in the ffmpeg document, such as time_base is equal to 1/frame rate.)
Upvotes: 0
Reputation: 49563
H.264 videos use a 90 kHz clock
for encoding timestamps
. Since your video is 30 fps
, the PTS delta between 2 successive frames should be 3000
instead of 20
.
A value of 20 indicates one or both of the following:
Your encoding clock (i.e. sampling rate) is configured incorrectly (to 600 Hz) for the given frame rate of 30 fps
Your frames per second is configured incorrectly (to 4500fps).
The general formula to calculate PTS delta is:
PTS delta = (1/fps) * Encoder sampling rate
Upvotes: 7