OSDN Git Service

stagefright-plugins: Fix video orientation
authorKeith Mok <kmok@cyngn.com>
Fri, 22 Jan 2016 00:40:55 +0000 (16:40 -0800)
committerKeith Mok <kmok@cyngn.com>
Fri, 22 Jan 2016 20:53:25 +0000 (12:53 -0800)
* Some videos are encoded rotated, but it also records the rotation in a
  rotation matrix. During playback, the player should apply the
  rotation matrix for display purpose.
  Right now, ffmpeg does decode the rotation matrix stored on the video file.
  But stagefright-plugins does not parse that meta data to stagefright.
  Added code to pass kKeyRotation to stagefright.
* Fixes CYNGNOS-1692

Change-Id: I718fd80c4695407fb214bab359d5cc255044725e

extractor/FFmpegExtractor.cpp
utils/ffmpeg_cmdutils.c
utils/ffmpeg_cmdutils.h

index c1e841d..1e6fb4b 100644 (file)
@@ -430,6 +430,23 @@ sp<MetaData> FFmpegExtractor::setVideoFormat(AVStream *stream)
     }
 
     if (meta != NULL) {
+        // rotation
+        double theta = get_rotation(stream);
+        int rotationDegrees = 0;
+
+        if (fabs(theta - 90) < 1.0) {
+            rotationDegrees = 90;
+        } else if (fabs(theta - 180) < 1.0) {
+            rotationDegrees = 180;
+        } else if (fabs(theta - 270) < 1.0) {
+            rotationDegrees = 270;
+        }
+        if (rotationDegrees != 0) {
+            meta->setInt32(kKeyRotation, rotationDegrees);
+        }
+    }
+
+    if (meta != NULL) {
         float aspect_ratio;
         int width, height;
 
index cdd0121..6f29e3a 100644 (file)
@@ -1,5 +1,7 @@
 #if 1
 #include "config.h"
+#include "libavutil/display.h"
+#include "libavutil/eval.h"
 #include "libavutil/log.h"
 #include "libavutil/opt.h"
 #include "libavformat/avformat.h"
@@ -16,6 +18,30 @@ void print_error(const char *filename, int err)
 }
 */
 
+double get_rotation(AVStream *st)
+{
+    AVDictionaryEntry *rotate_tag = av_dict_get(st->metadata, "rotate", NULL, 0);
+    uint8_t* displaymatrix = av_stream_get_side_data(st,
+                                                     AV_PKT_DATA_DISPLAYMATRIX, NULL);
+    double theta = 0;
+
+    if (rotate_tag && *rotate_tag->value && strcmp(rotate_tag->value, "0")) {
+        char *tail;
+        theta = av_strtod(rotate_tag->value, &tail);
+        if (*tail)
+            theta = 0;
+    }
+    if (displaymatrix && !theta)
+        theta = -av_display_rotation_get((int32_t*) displaymatrix);
+
+    theta -= 360*floor(theta/360 + 0.9/360);
+
+    if (fabs(theta - 90*round(theta/90)) > 2)
+        av_log(NULL, AV_LOG_WARNING, "Odd rotation angle.");
+
+    return theta;
+}
+
 int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
 {
     int ret = avformat_match_stream_specifier(s, st, spec);
index 1fd2f23..7833011 100644 (file)
@@ -22,6 +22,7 @@ extern "C" {
 struct AVDictionary;
 struct AVFormatContext;
 
+double get_rotation(AVStream *st);
 AVDictionary **setup_find_stream_info_opts(AVFormatContext *, AVDictionary *);
 
 #ifdef __cplusplus