Convert the Matroska stereo format to the Stereo3D format, and add a
Stereo3D side data to the stream.
Bump the doctype version supported.
Bug-Id: 728 / https://bugs.debian.org/757185
... | ... |
@@ -19,6 +19,8 @@ |
19 | 19 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
20 | 20 |
*/ |
21 | 21 |
|
22 |
+#include "libavutil/stereo3d.h" |
|
23 |
+ |
|
22 | 24 |
#include "matroska.h" |
23 | 25 |
|
24 | 26 |
const CodecTags ff_mkv_codec_tags[]={ |
... | ... |
@@ -103,3 +105,65 @@ const AVMetadataConv ff_mkv_metadata_conv[] = { |
103 | 103 |
{ "PART_NUMBER" , "track" }, |
104 | 104 |
{ 0 } |
105 | 105 |
}; |
106 |
+ |
|
107 |
+int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode) |
|
108 |
+{ |
|
109 |
+ AVPacketSideData *sd, *tmp; |
|
110 |
+ AVStereo3D *stereo; |
|
111 |
+ |
|
112 |
+ stereo = av_stereo3d_alloc(); |
|
113 |
+ if (!stereo) |
|
114 |
+ return AVERROR(ENOMEM); |
|
115 |
+ |
|
116 |
+ tmp = av_realloc_array(st->side_data, st->nb_side_data + 1, sizeof(*tmp)); |
|
117 |
+ if (!tmp) { |
|
118 |
+ av_freep(&stereo); |
|
119 |
+ return AVERROR(ENOMEM); |
|
120 |
+ } |
|
121 |
+ st->side_data = tmp; |
|
122 |
+ st->nb_side_data++; |
|
123 |
+ |
|
124 |
+ sd = &st->side_data[st->nb_side_data - 1]; |
|
125 |
+ sd->type = AV_PKT_DATA_STEREO3D; |
|
126 |
+ sd->data = (uint8_t *)stereo; |
|
127 |
+ sd->size = sizeof(*stereo); |
|
128 |
+ |
|
129 |
+ // note: the missing breaks are intentional |
|
130 |
+ switch (stereo_mode) { |
|
131 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO: |
|
132 |
+ stereo->type = AV_STEREO3D_2D; |
|
133 |
+ break; |
|
134 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT: |
|
135 |
+ stereo->flags |= AV_STEREO3D_FLAG_INVERT; |
|
136 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT: |
|
137 |
+ stereo->type = AV_STEREO3D_SIDEBYSIDE; |
|
138 |
+ break; |
|
139 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP: |
|
140 |
+ stereo->flags |= AV_STEREO3D_FLAG_INVERT; |
|
141 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM: |
|
142 |
+ stereo->type = AV_STEREO3D_TOPBOTTOM; |
|
143 |
+ break; |
|
144 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL: |
|
145 |
+ stereo->flags |= AV_STEREO3D_FLAG_INVERT; |
|
146 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR: |
|
147 |
+ stereo->type = AV_STEREO3D_CHECKERBOARD; |
|
148 |
+ break; |
|
149 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL: |
|
150 |
+ stereo->flags |= AV_STEREO3D_FLAG_INVERT; |
|
151 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR: |
|
152 |
+ stereo->type = AV_STEREO3D_LINES; |
|
153 |
+ break; |
|
154 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL: |
|
155 |
+ stereo->flags |= AV_STEREO3D_FLAG_INVERT; |
|
156 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR: |
|
157 |
+ stereo->type = AV_STEREO3D_COLUMNS; |
|
158 |
+ break; |
|
159 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL: |
|
160 |
+ stereo->flags |= AV_STEREO3D_FLAG_INVERT; |
|
161 |
+ case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR: |
|
162 |
+ stereo->type = AV_STEREO3D_FRAMESEQUENCE; |
|
163 |
+ break; |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ return 0; |
|
167 |
+} |
... | ... |
@@ -237,6 +237,7 @@ typedef enum { |
237 | 237 |
MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG = 12, |
238 | 238 |
MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR = 13, |
239 | 239 |
MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL = 14, |
240 |
+ MATROSKA_VIDEO_STEREOMODE_TYPE_NB, |
|
240 | 241 |
} MatroskaVideoStereoModeType; |
241 | 242 |
|
242 | 243 |
/* |
... | ... |
@@ -255,4 +256,6 @@ extern const CodecTags ff_mkv_codec_tags[]; |
255 | 255 |
extern const CodecMime ff_mkv_mime_tags[]; |
256 | 256 |
extern const AVMetadataConv ff_mkv_metadata_conv[]; |
257 | 257 |
|
258 |
+int ff_mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode); |
|
259 |
+ |
|
258 | 260 |
#endif /* AVFORMAT_MATROSKA_H */ |
... | ... |
@@ -123,6 +123,7 @@ typedef struct { |
123 | 123 |
uint64_t pixel_width; |
124 | 124 |
uint64_t pixel_height; |
125 | 125 |
uint64_t fourcc; |
126 |
+ uint64_t stereo_mode; |
|
126 | 127 |
} MatroskaTrackVideo; |
127 | 128 |
|
128 | 129 |
typedef struct { |
... | ... |
@@ -319,7 +320,7 @@ static EbmlSyntax matroska_track_video[] = { |
319 | 319 |
{ MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, |
320 | 320 |
{ MATROSKA_ID_VIDEODISPLAYUNIT, EBML_NONE }, |
321 | 321 |
{ MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_NONE }, |
322 |
- { MATROSKA_ID_VIDEOSTEREOMODE, EBML_NONE }, |
|
322 |
+ { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, |
|
323 | 323 |
{ MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, |
324 | 324 |
{ 0 } |
325 | 325 |
}; |
... | ... |
@@ -1786,6 +1787,13 @@ static int matroska_parse_tracks(AVFormatContext *s) |
1786 | 1786 |
av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, |
1787 | 1787 |
1000000000, track->default_duration, 30000); |
1788 | 1788 |
} |
1789 |
+ // add stream level stereo3d side data if it is a supported format |
|
1790 |
+ if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB && |
|
1791 |
+ track->video.stereo_mode != 10 && track->video.stereo_mode != 12) { |
|
1792 |
+ int ret = ff_mkv_stereo3d_conv(st, track->video.stereo_mode); |
|
1793 |
+ if (ret < 0) |
|
1794 |
+ return ret; |
|
1795 |
+ } |
|
1789 | 1796 |
} else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { |
1790 | 1797 |
st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
1791 | 1798 |
st->codec->sample_rate = track->audio.out_samplerate; |
... | ... |
@@ -1821,7 +1829,7 @@ static int matroska_read_header(AVFormatContext *s) |
1821 | 1821 |
ebml.version > EBML_VERSION || |
1822 | 1822 |
ebml.max_size > sizeof(uint64_t) || |
1823 | 1823 |
ebml.id_length > sizeof(uint32_t) || |
1824 |
- ebml.doctype_version > 2) { |
|
1824 |
+ ebml.doctype_version > 3) { |
|
1825 | 1825 |
av_log(matroska->ctx, AV_LOG_ERROR, |
1826 | 1826 |
"EBML header using unsupported features\n" |
1827 | 1827 |
"(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", |