mirror of https://git.ffmpeg.org/ffmpeg.git
h264: parse frame packing arrangement SEI messages and save relevant stereo3d information
This commit is contained in:
parent
7e244c6860
commit
5b10ef729f
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "libavutil/avassert.h"
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/imgutils.h"
|
#include "libavutil/imgutils.h"
|
||||||
|
#include "libavutil/stereo3d.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "cabac.h"
|
#include "cabac.h"
|
||||||
#include "cabac_functions.h"
|
#include "cabac_functions.h"
|
||||||
|
@ -2029,6 +2030,46 @@ static void decode_postinit(H264Context *h, int setup_finished)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (h->sei_frame_packing_present &&
|
||||||
|
h->frame_packing_arrangement_type >= 0 &&
|
||||||
|
h->frame_packing_arrangement_type <= 6 &&
|
||||||
|
h->content_interpretation_type > 0 &&
|
||||||
|
h->content_interpretation_type < 3) {
|
||||||
|
AVStereo3D *stereo = av_stereo3d_create_side_data(&cur->f);
|
||||||
|
if (!stereo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (h->frame_packing_arrangement_type) {
|
||||||
|
case 0:
|
||||||
|
stereo->type = AV_STEREO3D_CHECKERBOARD;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
stereo->type = AV_STEREO3D_LINES;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
stereo->type = AV_STEREO3D_COLUMNS;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (h->quincunx_subsampling)
|
||||||
|
stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
|
||||||
|
else
|
||||||
|
stereo->type = AV_STEREO3D_SIDEBYSIDE;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
stereo->type = AV_STEREO3D_TOPBOTTOM;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
stereo->type = AV_STEREO3D_FRAMESEQUENCE;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
stereo->type = AV_STEREO3D_2D;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (h->content_interpretation_type == 2)
|
||||||
|
stereo->flags = AV_STEREO3D_FLAG_INVERT;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME do something with unavailable reference frames
|
// FIXME do something with unavailable reference frames
|
||||||
|
|
||||||
/* Sort B-frames into display order */
|
/* Sort B-frames into display order */
|
||||||
|
|
|
@ -123,7 +123,8 @@ typedef enum {
|
||||||
SEI_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1)
|
SEI_BUFFERING_PERIOD = 0, ///< buffering period (H.264, D.1.1)
|
||||||
SEI_TYPE_PIC_TIMING = 1, ///< picture timing
|
SEI_TYPE_PIC_TIMING = 1, ///< picture timing
|
||||||
SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data
|
SEI_TYPE_USER_DATA_UNREGISTERED = 5, ///< unregistered user data
|
||||||
SEI_TYPE_RECOVERY_POINT = 6 ///< recovery point (frame # to decoder sync)
|
SEI_TYPE_RECOVERY_POINT = 6, ///< recovery point (frame # to decoder sync)
|
||||||
|
SEI_TYPE_FRAME_PACKING = 45, ///< frame packing arrangement
|
||||||
} SEI_Type;
|
} SEI_Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -585,6 +586,14 @@ typedef struct H264Context {
|
||||||
*/
|
*/
|
||||||
int prev_interlaced_frame;
|
int prev_interlaced_frame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* frame_packing_arrangment SEI message
|
||||||
|
*/
|
||||||
|
int sei_frame_packing_present;
|
||||||
|
int frame_packing_arrangement_type;
|
||||||
|
int content_interpretation_type;
|
||||||
|
int quincunx_subsampling;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bit set of clock types for fields/frames in picture timing SEI message.
|
* Bit set of clock types for fields/frames in picture timing SEI message.
|
||||||
* For each found ct_type, appropriate bit is set (e.g., bit 1 for
|
* For each found ct_type, appropriate bit is set (e.g., bit 1 for
|
||||||
|
|
|
@ -42,6 +42,7 @@ void ff_h264_reset_sei(H264Context *h)
|
||||||
h->sei_dpb_output_delay = 0;
|
h->sei_dpb_output_delay = 0;
|
||||||
h->sei_cpb_removal_delay = -1;
|
h->sei_cpb_removal_delay = -1;
|
||||||
h->sei_buffering_period_present = 0;
|
h->sei_buffering_period_present = 0;
|
||||||
|
h->sei_frame_packing_present = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int decode_picture_timing(H264Context *h)
|
static int decode_picture_timing(H264Context *h)
|
||||||
|
@ -175,6 +176,40 @@ static int decode_buffering_period(H264Context *h)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int decode_frame_packing_arrangement(H264Context *h)
|
||||||
|
{
|
||||||
|
int cancel;
|
||||||
|
int quincunx = 0;
|
||||||
|
int content = -1;
|
||||||
|
int type = -1;
|
||||||
|
|
||||||
|
get_ue_golomb(&h->gb); // frame_packing_arrangement_id
|
||||||
|
cancel = get_bits1(&h->gb); // frame_packing_arrangement_cancel_flag
|
||||||
|
if (cancel == 0) {
|
||||||
|
type = get_bits(&h->gb, 7); // frame_packing_arrangement_type
|
||||||
|
quincunx = get_bits1(&h->gb); // quincunx_sampling_flag
|
||||||
|
content = get_bits(&h->gb, 6); // content_interpretation_type
|
||||||
|
|
||||||
|
// the following skips: spatial_flipping_flag, frame0_flipped_flag,
|
||||||
|
// field_views_flag, current_frame_is_frame0_flag,
|
||||||
|
// frame0_self_contained_flag, frame1_self_contained_flag
|
||||||
|
skip_bits(&h->gb, 6);
|
||||||
|
|
||||||
|
if (quincunx == 0 && type != 5)
|
||||||
|
skip_bits(&h->gb, 16); // frame[01]_grid_position_[xy]
|
||||||
|
skip_bits(&h->gb, 8); // frame_packing_arrangement_reserved_byte
|
||||||
|
get_ue_golomb(&h->gb); // frame_packing_arrangement_repetition_period
|
||||||
|
}
|
||||||
|
skip_bits1(&h->gb); // frame_packing_arrangement_extension_flag
|
||||||
|
|
||||||
|
h->sei_frame_packing_present = (cancel == 0);
|
||||||
|
h->frame_packing_arrangement_type = type;
|
||||||
|
h->content_interpretation_type = content;
|
||||||
|
h->quincunx_subsampling = quincunx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int ff_h264_decode_sei(H264Context *h)
|
int ff_h264_decode_sei(H264Context *h)
|
||||||
{
|
{
|
||||||
while (get_bits_left(&h->gb) > 16) {
|
while (get_bits_left(&h->gb) > 16) {
|
||||||
|
@ -217,6 +252,11 @@ int ff_h264_decode_sei(H264Context *h)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
|
case SEI_TYPE_FRAME_PACKING:
|
||||||
|
ret = decode_frame_packing_arrangement(h);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type);
|
av_log(h->avctx, AV_LOG_DEBUG, "unknown SEI type %d\n", type);
|
||||||
skip_bits(&h->gb, 8 * size);
|
skip_bits(&h->gb, 8 * size);
|
||||||
|
|
Loading…
Reference in New Issue