I'm trying to read content within tags, but I'm not succeeding.
Here's what I'm trying:
int main()
{
TiXmlDocument *doc = new TiXmlDocument("simple-scene.xml");
doc->LoadFile();
cout << doc->FirstChildElement("width")->GetText();
return 0;
}
Here's the XML document:
<?xml version="1.0" encoding="utf-8"?>
<rt>
<image>
<width>800</width>
<height>600</height>
</image>
</rt>
Any help is appreciated!
You have to access from root element to the child elements such as this sample:
int main()
{
TiXmlDocument *doc = new TiXmlDocument("simple-scene.xml");
doc->LoadFile();
TiXmlElement* root = doc.FirstChildElement( "rt" );
if ( root )
{
TiXmlElement* image = root->FirstChildElement( "image" );
if ( image )
{
TiXmlElement* width = element->FirstChildElement( "width" );
if ( width )
{
std::string strWidth = width->GetText();
std::cout << width->Value();
}
}
}
return 0;
}
int main()
{
TiXmlDocument *doc = new TiXmlDocument("simple-scene.xml");
doc->LoadFile();
TiXmlElement *root = doc->FirstChildElement("rt");
TiXmlElement *image = root->FirstChildElement("image");
TiXmlElement *width = image->FirstChildElement("width");
cout << width->GetText();
return 0;
}
Of course you have to add checks that FirstChildElement isn't returned NULL. Each time.
Related
I am testing the Platform-Channels with the windows visual studio 2022.
I can pass the single value from the flutter UI while I get the battery value, but I want to send multi-data from flutter to the windows code.
Here is mine test code which I follow the flutter tutorial:
class _MyHomePageState extends State<MyHomePage> {
static const MethodChannel platform =
MethodChannel('samples.flutter.dev/battery');
String _batteryLevel = 'Unknown battery level.';
int value = 100;
Future<void> _getBatteryLevel(int fluval) async {
String batteryLevel;
try {
final int result = await platform.invokeMethod('getBatteryLevel', fluval);
batteryLevel = 'Battery level at $result % .';
} on PlatformException catch (e) {
batteryLevel = "Failed to get battery level: '${e.message}'.";
}
setState(() {
_batteryLevel = batteryLevel;
});
}
#override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () {
_getBatteryLevel(100);
},
child: const Text('Get Battery Level'),
),
Text(_batteryLevel),
],
),
),
);
}
}
and the windows side:
void initMethodChannel(flutter::FlutterEngine* flutter_instance) {
const static std::string channel_name("samples.flutter.dev/battery");
auto channel =
std::make_unique<flutter::MethodChannel<>>(
flutter_instance->messenger(), channel_name,
&flutter::StandardMethodCodec::GetInstance());
channel->SetMethodCallHandler(
[](const flutter::MethodCall<>& call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
// cheack method name called from dart
if (call.method_name().compare("getBatteryLevel") == 0) {
int battery_level = GetBatteryLevel();
const auto* flu_value = std::get_if<int>(call.arguments());
std::cout << typeid(flu_value).name() << std::endl;
if (!flu_value) {
result->Error("Missing required type parameter","Expected int");
}
std::cout << "From Flutter: " << *flu_value << std::endl;
if (battery_level != -1) {
result->Success(battery_level);
}
else {
result->Error("UNAVAILABLE", "Battery level not available.");
}
}
else {
result->NotImplemented();
}
});
}
if I want to send multi-data like this:
Future<void> _getBatteryLevel(int fluval, int data2,...,...) ...
How should I do or parse these two values fluval and data2 when call once invokeMethod?
Any examples that I can reference? or tips for the Windows UI design?
I try to search but the most answer is for the Android or IOS app, and the android answer is using call.argument("value") which you can choose specific data value to use but the windows only has call.arguments(); function call, I don't know how to get the specific data I want.
============================================================
[Update]
From the #Richard tips and example,
I made a test and it works, thanks #Richard!
Here is the Flutter UI example code: (inside the Stateful Widget State class), fluval= 100, fluval2 = 87
String _getBackV1 = 'Unknown Value 1.';
String _getBackV2 = 'Unknown Value 2.';
int value = 100;
Future<void> _testMapPassValue(int fluval, int fluval2) async {
String backValue1, backValue2;
try {
final Map<String, dynamic>? getReply = await platform
.invokeMapMethod<String, dynamic>('testPass',
<String, dynamic>{"fluval": fluval, "fluval2": fluval2});
backValue1 = "Get Back Value 1 from windows: ${getReply!["fluval"]}";
backValue2 = "Get Back Value 2 from windows: ${getReply!["fluval2"]}";
} on PlatformException catch (e) {
backValue1 = "Failed to get Value 1: '${e.message}'.";
backValue2 = "Failed to get Value 2: '${e.message}'.";
}
setState(() {
_getBackV1 = backValue1;
_getBackV2 = backValue2;
});
}
At the Windows side example code:
using flutter::EncodableList;
using flutter::EncodableMap;
using flutter::EncodableValue;
constexpr char testMapPassValue[] = "testPass";
constexpr char passKey1[] = "fluval";
constexpr char passKey2[] = "fluval2";
The method call handler:
if (call.method_name().compare(testMapPassValue) == 0) {
const auto* getArguments_flu = std::get_if<flutter::EncodableMap>(call.arguments());
assert(getArguments_flu);
return Flu_2_Win_MethodHandler(*getArguments_flu, std::move(result));
}
void Flu_2_Win_MethodHandler(
const EncodableMap& args, std::unique_ptr<flutter::MethodResult<>> result) {
int wins2fluValue1;
int wins2fluValue2;
EncodableMap win2fluMap;
const auto* flu2winsValue1 =
std::get_if<int>(ValueOrNull(args, passKey1));
if (!flu2winsValue1) {
return result->Error("argument_error",
std::string(passKey1) + " argument missing");
}
wins2fluValue1 = *flu2winsValue1;
std::cout << "From Flutter value1: " << *flu2winsValue1 << std::endl;
wins2fluValue1 = wins2fluValue1 + 10;
std::cout << "After calculate value1: " << wins2fluValue1 << std::endl;
const auto* flu2winsValue2 =
std::get_if<int>(ValueOrNull(args, passKey2));
if (!flu2winsValue2) {
return result->Error("argument_error",
std::string(passKey2) + " argument missing");
}
wins2fluValue2 = *flu2winsValue2;
std::cout << "From Flutter value1: " << *flu2winsValue2 << std::endl;
wins2fluValue2 = wins2fluValue2 + 20;
std::cout << "After calculate value2: " << wins2fluValue2 << std::endl;
win2fluMap.insert(std::pair<std::string, int>("fluval", wins2fluValue1));
win2fluMap.insert(std::pair<std::string, int>("fluval2", wins2fluValue2));
return result->Success(std::move(EncodableValue(win2fluMap)));
}
and the final result:
Thank you!
You can only pass a single entity as argument or result, but that entity can be any of the supported types (whether primitive - int, double, etc - or complex - list or map).
The mapping between Dart and C++ (native for Windows) types is:
// std::monostate -> null
// bool -> bool
// int32_t -> int
// int64_t -> int
// double -> double
// std::string -> String
// std::vector<uint8_t> -> Uint8List
// std::vector<int32_t> -> Int32List
// std::vector<int64_t> -> Int64List
// std::vector<float> -> Float32List
// std::vector<double> -> Float64List
// EncodableList -> List
// EncodableMap -> Map
(see encodable_value.h)
So, to send your two integers (fluval and data2) you could choose to put them in a Dart list (i.e. <int>[123, 456]) or a Dart map (i.e. {'fluval':123, 'data2':456}). At the native end, arguments will be either an EncodableList or EncodableMap.
Here's an example of how a complex Dart structure would appear at the native end:
// {
// 'flag': true,
// 'name': 'Thing',
// 'values': [1, 2.0, 4],
// }
// would correspond to:
// EncodableValue(EncodableMap{
// {EncodableValue("flag"), EncodableValue(true)},
// {EncodableValue("name"), EncodableValue("Thing")},
// {EncodableValue("values"), EncodableValue(EncodableList{
// EncodableValue(1),
// EncodableValue(2.0),
// EncodableValue(4),
// })},
// })
The camera plugin has some example usage (to get the arguments as a map):
const auto* arguments = std::get_if<flutter::EncodableMap>(method_call.arguments());
In the same file, check out the two utility functions:
// Looks for |key| in |map|, returning the associated value if it is present, or
// a nullptr if not.
const EncodableValue* ValueOrNull(const EncodableMap& map, const char* key) {
auto it = map.find(EncodableValue(key));
if (it == map.end()) {
return nullptr;
}
return &(it->second);
}
// Looks for |key| in |map|, returning the associated int64 value if it is
// present, or std::nullopt if not.
std::optional<int64_t> GetInt64ValueOrNull(const EncodableMap& map,
const char* key) {
auto value = ValueOrNull(map, key);
if (!value) {
return std::nullopt;
}
if (std::holds_alternative<int32_t>(*value)) {
return static_cast<int64_t>(std::get<int32_t>(*value));
}
auto val64 = std::get_if<int64_t>(value);
if (!val64) {
return std::nullopt;
}
return *val64;
}
and their typical usage:
const auto* camera_name =
std::get_if<std::string>(ValueOrNull(args, kCameraNameKey));
auto camera_id = GetInt64ValueOrNull(args, kCameraIdKey);
Here is the .proto which have one map:
map.proto
syntax = "proto3";
package demo;
message Person {
map<string, int32> family_list = 4;
}
Now I insert key and value from the Write_impl.cc
auto map = test.mutable_family_list();
string key = "faimly";
int val =20;
(*map)[key] = val;
std::cout<<"map = "<<(*map)[key]<<std::endl;
Below I read the value of key family in read_impl.cc
auto test = demo::Person::default_instance();
auto map = test.mutable_family_list();
std::cout<<"map = "<<(*map)["faimly"]<<std::endl;
Problem: I get 0 when reading the value of key "family"
You are using demo::Person::default_instance() which doesn't have the value you've stored earlier. It contains the default one.
You are using the subscript operator [] that doesn't throw an exception if the key is not found but the at() method does. You should use the at() method.
Here's an example of serialization and deserialization:
int main()
{
// Serialization
demo::Person sPerson;
const auto mutable_family_list = sPerson.mutable_family_list();
mutable_family_list->insert( { "abc", 42 } );
std::cout << mutable_family_list->at( "abc" ) << '\n';
const auto serialized = sPerson.SerializeAsString();
// Deserialization
demo::Person dPerson;
if ( !dPerson.ParseFromString( serialized ) )
{
std::cerr << "Deserialization failed!\n";
return -1;
}
const auto family_list = dPerson.family_list();
std::cout << family_list.at("abc") << '\n';
return 0;
}
Output:
42
42
Alternatively, you can find() first and then use the value like this:
const auto it = family_list.find( "abc" );
if ( it != family_list.end() )
{
std::cout << it->second << '\n';
}
This little program has to write an xml file.
Building the code I get the following error:
K:\Sergio\cpp\xml\sergio\cbp6s\main.cpp|32|error: 'base_tag' is an inaccessible base of 'tag'
In short, I have two classes derived from base_tag (xml_declaration and tag) and I want insert (or emplace) in a std::map some std::pair elements.
Building, the first insert works (std::pair<order::declaration, xml_declaration>), but the second fails (std::pair<order::root, tag_object>).
Between the object are derived from base_tag
Where am I wrong?
File tag.hpp :
#ifndef _TAG_HPP_
#define _TAG_HPP_
#include <string>
#include <vector>
#include <utility>
enum class tag_type
{
closing = -1,
autoclosed = 0,
opening = 1
};
using attribute = std::pair<std::string, std::string>;
class base_tag
{
public:
base_tag();
virtual ~base_tag();
virtual std::string get();
bool attribute_exists(std::string);
std::string get_attribute_value(std::string name);
bool add_attribute(std::string name, std::string value);
protected:
std::vector<std::pair<std::string, std::string>> _attributes;
};
// ------------------------------------------------------------
class xml_declaration : public base_tag
{
public:
xml_declaration();
~xml_declaration();
std::string get();
};
// ----------------------------------------------------------
class tag : base_tag
{
public:
tag(std::string name);
tag(std::string name, tag_type tt );
std::string get();
void set_ident(size_t ident);
protected:
std::string _name;
tag_type _tt;
};
#endif // _TAG_HPP_
File tag.cpp
#include "tag.hpp"
base_tag::base_tag()
{
}
base_tag::~base_tag()
{
_attributes.clear();
}
bool base_tag::attribute_exists(std::string name)
{
bool res = false;
for(auto & i : _attributes)
{
if (i.first == name)
res = true;
}
return res;
}
bool base_tag::add_attribute(std::string name, std::string value)
{
bool res = false;
if(!attribute_exists(name))
{
attribute a = std::make_pair(name, value);
_attributes.push_back(a);
res = true;
}
return res;
}
std::string base_tag::get()
{
return u8"<invalid_tag/>";
}
// -------------------------------------------------------
xml_declaration::xml_declaration(): base_tag()
{
add_attribute("version", "1.0");
add_attribute("encoding", "UTF-8");
add_attribute("standalone", "yes");
}
xml_declaration::~xml_declaration()
{ }
std::string xml_declaration::get()
{
std::string res = u8"<?xml";
for(auto & i : _attributes)
{
res.push_back(' ');
res += i.first;
res += u8"=\"";
res += i.second;
res += u8"\"";
}
res += u8" ?>";
return res;
}
// -------------------------------------------------------------
tag::tag(std::string name):base_tag(), _name(name)
{
_tt = tag_type::autoclosed;
}
tag::tag(std::string name, tag_type tt ): base_tag(), _name(name),
_tt(tt)
{ }
std::string tag::get()
{
std::string res = u8"";
bool with_attributes = !(_attributes.empty());
switch(_tt)
{
case tag_type::autoclosed : {
res = u8"<";
res += _name;
if(with_attributes)
{
for(auto & i : _attributes)
{
res.push_back(' ');
res += i.first;
res += u8"=\"";
res += i.second;
res += u8"\"";
}
};
res += u8"/>";
break;
}
case tag_type::opening : {
res = u8"<";
res += _name;
for(auto & i : _attributes)
{
res.push_back(' ');
res += i.first;
res += u8"=\"";
res += i.second;
res += u8"\"";
}
res += u8">";
break;
}
case tag_type::closing : {
res = u8"</";
res += _name;
res.push_back('>');
}
default : break;
}
return res;
}
File main.cpp
#include <iostream>
#include <map>
#include <utility>
#include "tag.hpp"
using namespace std;
enum class order
{
declaration = 0,
root = 1,
file_version = 4,
project = 10,
project_closing = 998,
root_closing = 1000
};
int main()
{
std::map<order, base_tag> tree;
xml_declaration decl;
cout << decl.get() << endl;
tag t1("project_file", tag_type::opening);
tag t2("project_file", tag_type::closing);
tree.insert(std::pair<order, base_tag>(order::declaration,
decl));
tree.insert(std::pair<order, base_tag>(order::root, t1));
tree.insert(std::pair<order, base_tag>(order::root, t2));
// tree.emplace(std::pair<order, base_tag>(order::root_closing, t1));
cout << tree.size() << endl;
return 0;
}
I'm using Code::Blocks with GCC 5.1.0 (on Windows 10).
As the error message says, tag inherits base_tag privately. If you change its headline into
class tag: public base_tag;
(same as your xml_declaration which inherits base_tag publicly) then it will officially be-a base tag.
A more serious problem is that you try to store instances of inherited classes in a container of a base class by value. What happens then is, objects get sliced and lose their whole derived functionality; you put an object of a derived class into a map, but you actually store an object of a based class in it (that's the reason some people tend to say polymorphic base classes should necessarily be abstract.) Use (smart) pointers or reference_wrappers as map's mapped type.
I wrote 2 threads to decode RTSP stream from IP camera as below:
RTSP_read_paket function used to read Packets from RTSP link, packets stored in a queue named Packet_buf.
std::queue<AVPacket> Packet_buf;
bool pkt_pending_k = false;
int RTSP_read_packet (string url)
{
rtsp_init(url);
int ret;
AVPacket packet;
av_init_packet(&packet);
while(1)
{
ret = av_read_frame(pFormatCtx,&packet);
if(ret==0)
{
if (packet.stream_index == video_stream_index)
{
Packet_buf.push(packet);
if((ready1 == false))
{
ready1 = true;
conv1.notify_one();
}
}
av_packet_unref(&packet);
cout<<"number of RTSP packet: "<<Packet_buf.size()<<endl;
}
}
return 0;
}
ffmpeg_decode read packets from Packet_buf to decode frames
AVFrame ffmpeg_decode( void )
{
AVPacket avpkt;
av_init_packet(&avpkt);
int ret;
conv1.wait(lk1,[]{return ready1;});
while(1)
{
while(1)
{
ret = avcodec_receive_frame(pCodecCtx,pFrame);
if(ret == AVERROR(EAGAIN)||ret==AVERROR_EOF){
break;
}
return pFrame;
}
if(!Packet_buf.empty())
{
if(pkt_pending_k == false)
{
avpkt = Packet_buf.front();
Packet_buf.pop();
}else{
pkt_pending_k = false;
}
}
ret = avcodec_send_packet(pCodecCtx, &avpkt); //program halting here
cout<<"-------------> ret = "<<ret<<endl;
if(ret==AVERROR(EAGAIN))
{
pkt_pending_k = true;
}
if(ret<0||ret==AVERROR_EOF)
{
cout<<"avcodec_send_packet: "<<ret<<endl;
break;
}
}
}
int main () {
thread Camera2_readPackets(RTSP_read_packet,url);
thread Camera2_decode(ffmpeg_decode,url);
Camera2_decode.join();
return 0;
}
My program halt at line:
ret = avcodec_send_packet(pCodecCtx, &avpkt);
Anyone can help me find the problem, thanks !
P/s:
rtsp_init function:
int rtsp_init (string url)
{
av_register_all();
avdevice_register_all();
avcodec_register_all();
avformat_network_init();
const char *filenameSrc = url.c_str();
pFormatCtx = avformat_alloc_context();
if ( pFormatCtx == NULL )
return -8;
AVDictionary *options = NULL;
av_dict_set(&options,"rtsp_flags","prefer_tcp",0);
av_dict_set(&options,"stimeout","1000000",0);
int avret = avformat_open_input( &pFormatCtx, filenameSrc, NULL, &options );
av_dict_free(&options);
if ( avret != 0 ) {
std::cout << "Open File Error 12" << std::endl;
return -12;
}
avret = avformat_find_stream_info( pFormatCtx, NULL );
if ( avret < 0 ) {
std::cout << "Get Stream Information Error 13" << std::endl;
avformat_close_input( &pFormatCtx );
pFormatCtx = NULL;
return -13;
}
av_dump_format( pFormatCtx, 0, filenameSrc, 0 );
video_stream_index = av_find_best_stream(pFormatCtx,AVMEDIA_TYPE_VIDEO,-1,-1,NULL,0);
if ( video_stream_index < 0 ) {
std::cout << "Video stream was not found Error 14" << std::endl;
avformat_close_input( &pFormatCtx );
pFormatCtx = NULL;
return -14;
}
pCodecCtx = avcodec_alloc_context3(NULL);
avret = avcodec_parameters_to_context(pCodecCtx,pFormatCtx->streams[video_stream_index]->codecpar);
if(avret<0)
{
std::cout << "codec not found Error 15" << std::endl;
return -15;
}
pCodec = avcodec_find_decoder( pCodecCtx->codec_id );
avret = avcodec_open2( pCodecCtx, pCodec, NULL );
if ( avret < 0) {
std::cout << "Open Codec Error 16" << std::endl;
return -16;
}
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
pFrame->width = pCodecCtx->width;
pFrame->height = pCodecCtx->height;
pFrame->format = pCodecCtx->pix_fmt;
avret = av_frame_get_buffer(pFrame,0);
if (avret < 0)
{
return -17;
}
pFrameRGB->width = pCodecCtx->width;
pFrameRGB->height = pCodecCtx->height;
pFrameRGB->format = AV_PIX_FMT_BGR24;
avret = av_frame_get_buffer(pFrameRGB, 0);
if (avret < 0)
{
return -18;
}
return ( EXIT_SUCCESS );
}
When I use the mpeg4 or h264 encoders, I am able to successfully encode images to make a valid AVI file using the API for ffmpeg 3.1.0. However, when I use the Quick Sync encoder (h264_qsv), avcodec_encode_video2 will hang some of the time. I found that when using images that are 1920x1080, it was rare that avcodec_encode_video2 would hang. When using 256x256 images, it was very likely that the function would hang.
I have created the test code below that demonstrates the hang of avcodec_encode_video2. The code will create a 1000 frame, 256x256 AVI with a bit rate of 400000. The frames are simply allocated, so the output video should just be green frames.
The problem was observed using Windows 7 and Windows 10, using the 32-bit or 64-bit test application.
If anyone has any idea on how I can avoid the avcodec_encode_video2 hang I would be very grateful! Thanks in advance for any assistance.
extern "C"
{
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include "avcodec.h"
#include "avformat.h"
#include "swscale.h"
#include "avutil.h"
#include "imgutils.h"
#include "opt.h"
#include <rational.h>
}
#include <iostream>
// Globals
AVCodec* m_pCodec = NULL;
AVStream *m_pStream = NULL;
AVOutputFormat* m_pFormat = NULL;
AVFormatContext* m_pFormatContext = NULL;
AVCodecContext* m_pCodecContext = NULL;
AVFrame* m_pFrame = NULL;
int m_frameIndex;
// Output format
AVPixelFormat m_pixType = AV_PIX_FMT_NV12;
// Use for mpeg4
//AVPixelFormat m_pixType = AV_PIX_FMT_YUV420P;
// Output frame rate
int m_frameRate = 30;
// Output image dimensions
int m_imageWidth = 256;
int m_imageHeight = 256;
// Number of frames to export
int m_frameCount = 1000;
// Output file name
const char* m_fileName = "c:/test/test.avi";
// Output file type
const char* m_fileType = "AVI";
// Codec name used to encode
const char* m_encoderName = "h264_qsv";
// use for mpeg4
//const char* m_encoderName = "mpeg4";
// Target bit rate
int m_targetBitRate = 400000;
void addVideoStream()
{
m_pStream = avformat_new_stream( m_pFormatContext, m_pCodec );
m_pStream->id = m_pFormatContext->nb_streams - 1;
m_pStream->time_base = m_pCodecContext->time_base;
m_pStream->codec->pix_fmt = m_pixType;
m_pStream->codec->flags = m_pCodecContext->flags;
m_pStream->codec->width = m_pCodecContext->width;
m_pStream->codec->height = m_pCodecContext->height;
m_pStream->codec->time_base = m_pCodecContext->time_base;
m_pStream->codec->bit_rate = m_pCodecContext->bit_rate;
}
AVFrame* allocatePicture( enum AVPixelFormat pix_fmt, int width, int height )
{
AVFrame *frame;
frame = av_frame_alloc();
if ( !frame )
{
return NULL;
}
frame->format = pix_fmt;
frame->width = width;
frame->height = height;
int checkImage = av_image_alloc( frame->data, frame->linesize, width, height, pix_fmt, 32 );
if ( checkImage < 0 )
{
return NULL;
}
return frame;
}
bool initialize()
{
AVRational frameRate;
frameRate.den = m_frameRate;
frameRate.num = 1;
av_register_all();
m_pCodec = avcodec_find_encoder_by_name(m_encoderName);
if( !m_pCodec )
{
return false;
}
m_pCodecContext = avcodec_alloc_context3( m_pCodec );
m_pCodecContext->width = m_imageWidth;
m_pCodecContext->height = m_imageHeight;
m_pCodecContext->time_base = frameRate;
m_pCodecContext->gop_size = 0;
m_pCodecContext->pix_fmt = m_pixType;
m_pCodecContext->codec_id = m_pCodec->id;
m_pCodecContext->bit_rate = m_targetBitRate;
av_opt_set( m_pCodecContext->priv_data, "+CBR", "", 0 );
return true;
}
bool startExport()
{
m_frameIndex = 0;
char fakeFileName[512];
int checkAllocContext = avformat_alloc_output_context2( &m_pFormatContext, NULL, m_fileType, fakeFileName );
if ( checkAllocContext < 0 )
{
return false;
}
if ( !m_pFormatContext )
{
return false;
}
m_pFormat = m_pFormatContext->oformat;
if ( m_pFormat->video_codec != AV_CODEC_ID_NONE )
{
addVideoStream();
int checkOpen = avcodec_open2( m_pCodecContext, m_pCodec, NULL );
if ( checkOpen < 0 )
{
return false;
}
m_pFrame = allocatePicture( m_pCodecContext->pix_fmt, m_pCodecContext->width, m_pCodecContext->height );
if( !m_pFrame )
{
return false;
}
m_pFrame->pts = 0;
}
int checkOpen = avio_open( &m_pFormatContext->pb, m_fileName, AVIO_FLAG_WRITE );
if ( checkOpen < 0 )
{
return false;
}
av_dict_set( &(m_pFormatContext->metadata), "title", "QS Test", 0 );
int checkHeader = avformat_write_header( m_pFormatContext, NULL );
if ( checkHeader < 0 )
{
return false;
}
return true;
}
int processFrame( AVPacket& avPacket )
{
avPacket.stream_index = 0;
avPacket.pts = av_rescale_q( m_pFrame->pts, m_pStream->codec->time_base, m_pStream->time_base );
avPacket.dts = av_rescale_q( m_pFrame->pts, m_pStream->codec->time_base, m_pStream->time_base );
m_pFrame->pts++;
int retVal = av_interleaved_write_frame( m_pFormatContext, &avPacket );
return retVal;
}
bool exportFrame()
{
int success = 1;
int result = 0;
AVPacket avPacket;
av_init_packet( &avPacket );
avPacket.data = NULL;
avPacket.size = 0;
fflush(stdout);
std::cout << "Before avcodec_encode_video2 for frame: " << m_frameIndex << std::endl;
success = avcodec_encode_video2( m_pCodecContext, &avPacket, m_pFrame, &result );
std::cout << "After avcodec_encode_video2 for frame: " << m_frameIndex << std::endl;
if( result )
{
success = processFrame( avPacket );
}
av_packet_unref( &avPacket );
m_frameIndex++;
return ( success == 0 );
}
void endExport()
{
int result = 0;
int success = 0;
if (m_pFrame)
{
while ( success == 0 )
{
AVPacket avPacket;
av_init_packet( &avPacket );
avPacket.data = NULL;
avPacket.size = 0;
fflush(stdout);
success = avcodec_encode_video2( m_pCodecContext, &avPacket, NULL, &result );
if( result )
{
success = processFrame( avPacket );
}
av_packet_unref( &avPacket );
if (!result)
{
break;
}
}
}
if (m_pFormatContext)
{
av_write_trailer( m_pFormatContext );
if( m_pFrame )
{
av_frame_free( &m_pFrame );
}
avio_closep( &m_pFormatContext->pb );
avformat_free_context( m_pFormatContext );
m_pFormatContext = NULL;
}
}
void cleanup()
{
if( m_pFrame || m_pCodecContext )
{
if( m_pFrame )
{
av_frame_free( &m_pFrame );
}
if( m_pCodecContext )
{
avcodec_close( m_pCodecContext );
av_free( m_pCodecContext );
}
}
}
int main()
{
bool success = true;
if (initialize())
{
if (startExport())
{
for (int loop = 0; loop < m_frameCount; loop++)
{
if (!exportFrame())
{
std::cout << "Failed to export frame\n";
success = false;
break;
}
}
endExport();
}
else
{
std::cout << "Failed to start export\n";
success = false;
}
cleanup();
}
else
{
std::cout << "Failed to initialize export\n";
success = false;
}
if (success)
{
std::cout << "Successfully exported file\n";
}
return 1;
}
The problem no longer occurs now that I have updated to the latest IntelĀ® Graphics Driver (version 15.45.10.4542)