Skip to content

Add automatic flip method that rotates video based on video tags. #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions camera/gstCamera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ bool gstCamera::buildLaunchStr()

if( mOptions.resource.protocol == "csi" )
{
if( mOptions.flipMethod == videoOptions::FLIP_AUTOMATIC || mOptions.flipMethod == videoOptions::FLIP_UNDEFINED )
mOptions.flipMethod = videoOptions::FLIP_NONE;
#if NV_TENSORRT_MAJOR > 4
// on newer JetPack's, it's common for CSI camera to need flipped
// so here we reverse FLIP_NONE with FLIP_ROTATE_180
Expand Down
35 changes: 34 additions & 1 deletion codec/gstDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,39 @@ bool gstDecoder::discover()
return false;
}

// Look at video tags and extract rotation
const GstTagList* tags = gst_discoverer_stream_info_get_tags(streamInfo);
if( tags ) {
// Extract tags
gchar* tagsStr = gst_tag_list_to_string(tags);
LogVerbose(LOG_GSTREAMER "gstDecoder -- tags: %s\n", tagsStr);
g_free(tagsStr);

// If flip method is not finalized, check for rotation tags in the video.
if( mOptions.flipMethod == videoOptions::FLIP_AUTOMATIC || mOptions.flipMethod == videoOptions::FLIP_UNDEFINED ) {
gchar* rotationTag;
const bool foundRotationTag = gst_tag_list_get_string(tags, "image-orientation", &rotationTag);
if (foundRotationTag) {
if( strcasecmp(rotationTag, "rotate-90") == 0 )
mOptions.flipMethod = videoOptions::FLIP_CLOCKWISE;
else if( strcasecmp(rotationTag, "rotate-180") == 0 )
mOptions.flipMethod = videoOptions::FLIP_ROTATE_180;
else if( strcasecmp(rotationTag, "rotate-270") == 0 )
mOptions.flipMethod = videoOptions::FLIP_COUNTERCLOCKWISE;
LogVerbose(LOG_GSTREAMER "gstDecoder -- rotation tag: %s\n", rotationTag);
} else {
LogVerbose(LOG_GSTREAMER "gstDecoder -- found no rotation tag\n");
}
}
} else {
LogVerbose(LOG_GSTREAMER "gstDecoder -- found no tags\n");
}

// If flip is still not set after looking at tags, default to FLIP_NONE
if( mOptions.flipMethod == videoOptions::FLIP_AUTOMATIC || mOptions.flipMethod == videoOptions::FLIP_UNDEFINED ) {
mOptions.flipMethod = videoOptions::FLIP_NONE;
}

// retrieve video resolution
guint width = gst_discoverer_video_info_get_width(videoInfo);
guint height = gst_discoverer_video_info_get_height(videoInfo);
Expand All @@ -370,7 +403,7 @@ bool gstDecoder::discover()
const float framerate = framerate_num / framerate_denom;

LogVerbose(LOG_GSTREAMER "gstDecoder -- discovered video resolution: %ux%u (framerate %f Hz)\n", width, height, framerate);

// disable re-scaling if the user's custom size matches the feed's
if( mCustomSize && mOptions.width == width && mOptions.height == height )
mCustomSize = false;
Expand Down
13 changes: 9 additions & 4 deletions video/videoOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ videoOptions::videoOptions()
zeroCopy = true;
ioType = INPUT;
deviceType = DEVICE_DEFAULT;
flipMethod = FLIP_DEFAULT;
flipMethod = FLIP_UNDEFINED;
codec = CODEC_UNKNOWN;
}

Expand Down Expand Up @@ -137,6 +137,9 @@ bool videoOptions::Parse( const char* URI, const commandLine& cmdLine, videoOpti

flipMethod = videoOptions::FlipMethodFromStr(flipStr);

if( flipMethod == videoOptions::FLIP_UNDEFINED )
flipMethod = (type == INPUT) ? videoOptions::FLIP_INPUT_DEFAULT : videoOptions::FLIP_OUTPUT_DEFUALT;

// codec
const char* codecStr = (type == INPUT) ? cmdLine.GetString("input-codec")
: cmdLine.GetString("output-codec");
Expand Down Expand Up @@ -284,6 +287,8 @@ const char* videoOptions::FlipMethodToStr( videoOptions::FlipMethod flip )
case FLIP_UPPER_RIGHT_DIAGONAL: return "upper-right-diagonal";
case FLIP_VERTICAL: return "vertical";
case FLIP_UPPER_LEFT_DIAGONAL: return "upper-left-diagonal";
case FLIP_AUTOMATIC: return "automatic";
case FLIP_UNDEFINED: return "undefined";
}
return nullptr;
}
Expand All @@ -293,17 +298,17 @@ const char* videoOptions::FlipMethodToStr( videoOptions::FlipMethod flip )
videoOptions::FlipMethod videoOptions::FlipMethodFromStr( const char* str )
{
if( !str )
return FLIP_DEFAULT;
return FLIP_UNDEFINED;

for( int n=0; n <= FLIP_UPPER_LEFT_DIAGONAL; n++ )
for( int n=0; n <= FLIP_UNDEFINED; n++ )
{
const FlipMethod value = (FlipMethod)n;

if( strcasecmp(str, FlipMethodToStr(value)) == 0 )
return value;
}

return FLIP_DEFAULT;
return FLIP_UNDEFINED;
}


Expand Down
6 changes: 5 additions & 1 deletion video/videoOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,10 @@ struct videoOptions
FLIP_UPPER_RIGHT_DIAGONAL, /**< Flip across upper right/lower left diagonal */
FLIP_VERTICAL, /**< Flip vertically */
FLIP_UPPER_LEFT_DIAGONAL, /**< Flip across upper left/lower right diagonal */
FLIP_DEFAULT = FLIP_NONE /**< Default setting (none) */
FLIP_AUTOMATIC, /**< Choose rotation based on video tag */
FLIP_UNDEFINED,
FLIP_INPUT_DEFAULT = FLIP_AUTOMATIC, /**< Default for video input */
FLIP_OUTPUT_DEFUALT = FLIP_NONE /**< Default for video output */
};

/**
Expand All @@ -168,6 +171,7 @@ struct videoOptions
* - `vertical-flip` (Flip vertically)
* - `upper-right-diagonal` (Flip across upper right/lower left diagonal)
* - `upper-left-diagonal` (Flip across upper left/lower right diagonal)
* - `automatic` (Choose rotation based on video tag)
*/
FlipMethod flipMethod;

Expand Down