Perfect Forwarding: std::forward and std::move


Based on the source code below, here is the forwarding result:
Input parameter                    Forwarded to
int intNonConst:                     (int&)
const int intConst:                  (const int&)
6(just a literal):                        (int&&) or if (int&&) doesn’t exist, to (const int& i)
std::move(intNonConst)):      (int&&)
int IntTemp():                          (int&&)
Why std::forward: otherwise, when a rvalue is passed, e.g. 6, std::move or IntTemp(), it gets forwarded to &, instead of &&.
Why std::move: so that a lvalue such as intNonConst can be treated as rvalue, and therefore be forwarded to &&
Summary: std::forward is to deal with rvalue forwarding, and it does not affect rvalue reference, regardless of constness

int IntTemp() { return 0; }
void TestForwardingFuncCalled(const int& i)
{
	cout << "const &" << endl;
};
void TestForwardingFuncCalled(int& i)
{
	cout << "&" << endl;
};
void TestForwardingFuncCalled(int&& i)
{
	cout << "&& " << endl;
};

template  void TestForwardingTemplateFunc(T&& t)
{
	cout << "Results with std::forward" << endl;
	TestForwardingFuncCalled(std::forward(t));
	cout << "Results without std::forward" << endl;
	TestForwardingFuncCalled(t);
}

void TestForwarding()
{
	int intNonConst = 2;
	const int intConst = 3;
	TestForwardingTemplateFunc(intNonConst); //with std::forward: (int&)", without std::forward: same
	TestForwardingTemplateFunc(intConst); //with std::forward: (const int&)", without std::forward: same
	TestForwardingTemplateFunc(6); //with std::forward: (int&&) or if (int&&) doesn't exist, to (const int& i), without std::forward: (int&)
	TestForwardingTemplateFunc(std::move(intNonConst)); //with std::forward: (int&&), without std::forward: (int&)
	TestForwardingTemplateFunc(IntTemp());  //with std::forward: (int&&), without std::forward: (int&)
}
void main()
{
	TestForwarding();
}

 

Advertisements

Adaptive Bitrate HLS Generation


MaxxSports has two variant streams for each camera, high and low resolution, generated by ffmpeg. Player can switch between the two resolutions based on bandwidth.

There are three playlists in this sample setup; master.m3u8 has two variant playlists:
var_0.m3u8: 426×240, with original resolution from input mp4 file
var_1.m3u8: 128×86, transcoded with parameter -s:v:1 128×86

Command used to generate the three playlists:
set FF=2018\bin\ffmpeg.exe
set MEDIA=Gym2017bshort.mp4    : to be replaced by rtsp://… for live camera feed.
%FF% -i %MEDIA% -s:v:1 128×86 -map 0:v -map 0:a -map 0:v -map 0:a -f hls -master_pl_name master.m3u8 -var_stream_map “v:0,a:0 v:1,a:1” var_%v.m3u8

Play URL: http://riowing.net/ABR/master.m3u8 or http://riowing.net/ABR/var_0.m3u8 or var_1.m3u8

This feature, var_stream_map, was added to ffmpeg in November 2017.
ffmpeg version is ffmpeg-20180925-a7429d8-win64-static 4.02, downloaded from ffmpeg.zeranoe.com

Sample Bayer Video Posted


I am posting this Bayer video file, because, unlike other raw video such as YUV, I found no Bayer video on google.

The hardware is in the picture attached:

  1. Camera: Smartek UCC2461C, Optical Format 2/3
  2. Lens: Theia ML410M 4-10mm
  3. The C-mount connects the camera, left half, and  the lens, the right half.

The data:

  1. Bayer RGGB 8 bit per pixel, width 520, hight 512, 10 FPS, 100 frames, 26MB.
  2. Download video here: http://riowing.net/media/Inside100frames.bay

How to watch:

  1. ffmpeg converts Bayer to YUV, and the .yuv can be played by “YUV File Player”.
  2. The output yuv420 file, Inside100frames.yuv, has to be exact 1.5 times the size of the input bayer_rggb8 Inside100frames.bay.
  3. Here is the command: $ffmpeg -f rawvideo -vcodec rawvideo -s 520×512 -pix_fmt bayer_rggb8 -i Inside100frames.bay -vcodec rawvideo -pix_fmt yuv420p Inside100frames.yuv

This camera only records one color component for each pixel, which explains Bayer file is smaller than YUV.BayerPost

typename vs class (Visual Studio 2010)


Under what circumstances does NOT ‘class’ replace ‘typename’?

struct C
{
class CC{};
typedef CC CC2;
};
template<class T> //using 'class' is fine
struct D
{
typename T::CC2 c1; //'typename' cannot be prelaced by 'class'
class T::CC c2; //using 'class' is fine
//T::CC c3; //error: 'T::CC' : dependent name is not a type
//class T::CC2 c4; //error C2242: typedef name cannot follow class/struct/union
//T::CC2 c5; //error: 'T::CC2' : dependent name is not a type
};
D<C> a;

Summary: if the subtype if not typedef-ed, class can do the job of typename.
Otherwise, it has to be typename.