I'm trying to write a chunk of a mp4 file to a .ts file, which does not yet exist.
So first I create AVFormatContext this way:
AVOutputFormat *oformat = av_guess_format( NULL,
"mpegts",
"video/x-mpegts" );
AVFormatContext * outFormatContext = NULL;
avformat_alloc_output_context2( &outFormatContext, oformat, NULL, dst_file)
outFormatContext is created and outFormatContext->oformat is set to oformat. Then I open I/O context on outFormatContext:
avio_open(&outFormatContext->pb, dst_file, AVIO_FLAG_WRITE)
avformat_write_header( outFormatContext, NULL );
according to this this is enough for avformat_write_header to work but it fails with error "invalid argument".
What else needs to be done to successfully write the header?
Although it's a little bit late, I hope it would be helpful.
Here is my way to call avformat_write_header, you should have a stream provided to write the header.
AVFormatContext* pOutFormatContext;
AVOutputFormat* avOutputFormat;
if ((avOutputFormat = av_guess_format(NULL, "mp4", "video/mp4")) == NULL) {
cerr << "Could not guess output format" << endl;
return -1;
}
avformat_alloc_output_context2(&pOutFormatContext,
av_guess_format("mp4", NULL, "video/mp4"), NULL, NULL);
if (pOutFormatContext == NULL) {
cerr << "Could not allocate output context" << endl;
return -1;
}
for (int i = 0; i < avFormatContext->nb_streams; i++) {
AVStream* inAVStream = avFormatContext->streams[i];
AVStream* outAVStream = avformat_new_stream(pOutFormatContext, inAVStream->codec->codec);
if (avcodec_copy_context(outAVStream->codec, inAVStream->codec) < 0) {
cerr << "Failed to copy codec context" << endl;
return -1;
}
outAVStream->codec->codec_tag = 0;
if (pOutFormatContext->oformat->flags & AVFMT_GLOBALHEADER) {
outAVStream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
}
}
avio_open(&pOutFormatContext->pb, "test.mp4", AVIO_FLAG_READ_WRITE);
if (pOutFormatContext->pb == NULL) {
cerr << "Could not open for writing" << endl;
return -1;
}
if (avformat_write_header(pOutFormatContext, NULL) != 0) {
cerr << "Could not write header" << endl;
return -1;
}
Related
I'm trying to authenticate to an Active Directory domain using gsasl. I've already kinit'd as the Administrator. I've tried to follow the test code in gsasl tests/gssapi.c, but the code below is failing with GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR when calling gsasl_step64().
static int callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
{
int ret = GSASL_NO_CALLBACK;
switch (prop) {
case GSASL_AUTHZID:
gsasl_property_set(sctx, GSASL_AUTHZID, "Administrator");
ret = GSASL_OK;
break;
case GSASL_SERVICE:
gsasl_property_set(sctx, prop, "host");
ret = GSASL_OK;
break;
case GSASL_HOSTNAME:
char hostname[HOST_NAME_MAX];
gethostname(hostname, HOST_NAME_MAX);
gsasl_property_set(sctx, prop, hostname);
ret = GSASL_OK;
break;
default:
break;
}
return ret;
}
int main()
{
Gsasl *ctx = NULL;
Gsasl_session *session;
char *s1 = NULL, *s2 = NULL;
int ret;
ret = gsasl_init(&ctx);
if (ret != GSASL_OK) {
cerr << "gsasl_init failed" << endl;
return ret;
}
if (!gsasl_client_support_p(ctx, "GSSAPI")) {
cerr << "No support for GSSAPI." << endl;
return 77;
}
gsasl_callback_set(ctx, callback);
ret = gsasl_client_start(ctx, "GSSAPI", &session);
if (ret != GSASL_OK) {
cerr << "gsasl_client_start failed" << endl;
return ret;
}
do {
ret = gsasl_step64(session, s2, &s1);
gsasl_free(s2);
if (ret != GSASL_OK && ret != GSASL_NEEDS_MORE) {
cerr << "gsasl_step64 failed " << ret << endl;
return ret;
}
} while (ret != GSASL_OK);
if (s1) {
gsasl_free(s1);
}
gsasl_finish(session);
}
Does anyone see what I'm doing wrong?
Not really a clear answer because I don't use AD currently, so I can't verify my answer. But to localize the issue:
I would try the examples first. Maybe this test is desired to fail. If it doesn't work with the examples, I would investigate the source of library of the GNU SASL library.
Here is an extract from the source of the library, which throws this error:
maj_stat = gss_init_sec_context (&min_stat,
GSS_C_NO_CREDENTIAL,
&state->context,
state->service,
state->mech_oid,
GSS_C_MUTUAL_FLAG,
0,
&state->cb,
buf,
&actual_mech_type,
&state->token, &ret_flags, NULL);
if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;
As you can see, the function gss_init_sec_context() is called, In the if clause only GSS_S_COMPLETE and GSS_S_CONTINUE_NEEDED will be tested. But gss_init_sec_context() has many more status codes. So I would change the code of the library and print out a clearer error code, why it doesn't work.
There was also an issue in WINBIND/SAMBA, don't know if you use SAMBA, which throws an unspecified error in this specific function.
I want to modify the dhcp4 source code to notify the ddns server to set the dynamic domain name when assigning the lease, but I added the nanomsg statement in dhcp4_srv.cc. When my nanomsg performs shutdown or close, the dhcp4 service will automatically close. This is why there is no other way to implement dynamic domain names (my dynamic domain name mainly sends the field set by the foreground and the mac address and IP address to the ddns server, or it may be the login account of the foreground).
Someone can help me? thank you very much.
if (lease) {
// We have a lease! Let's set it in the packet and send it back to
// the client.
// 我们有租约! 让我们在数据包中进行设置,然后将其发送回客户端。
if (fake_allocation) {
//租约建议
LOG_INFO(lease4_logger, DHCP4_LEASE_ADVERT)
.arg(query->getLabel())
.arg(lease->addr_.toText());
} else {
//成功授予租约
LOG_INFO(lease4_logger, DHCP4_LEASE_ALLOC)
.arg(query->getLabel())
.arg(lease->addr_.toText())
.arg(lease->valid_lft_);
int rc = 0;
int pair_socket = 0;
int str_len = 0;
char buf[256] = { 0 };
char buf1[256] = { 0 };
int timeo = 5000;
//计算长度
str_len = strlen(HELLOWORLD);
//初始化socket
pair_socket = nn_socket(1, NN_PAIR);
if (pair_socket == -1) {
printf("nn_socket failed! error: %s.\n", nn_err_strerror(errno));
//system("pause");
nn_err_abort();
//return 0;
}
//设置超时
rc = nn_setsockopt(pair_socket, 0, NN_SNDTIMEO, &timeo, sizeof(timeo));
rc = nn_setsockopt(pair_socket, 0, NN_RCVTIMEO, &timeo, sizeof(timeo));
//连接服务端
rc = nn_connect(pair_socket, SOCKET_ADDRESS2);
if (rc < 0) {
printf("bind failed! error: %s.\n", nn_err_strerror(errno));
//system("pause");
nn_err_abort();
//return 0;
}
//将hello world复制到buf中
memcpy(buf, HELLOWORLD, str_len);
//发送数据
rc = nn_send(pair_socket, buf, str_len, 0);
if (rc < 0) {
printf("nn_send failed! error: %s.rc = %d.\n", nn_err_strerror(errno), rc);
}
//打印
printf("send:%s\n", buf);
//这里主要是测试使用,平时项目不要使用标签
//接收数据
rc = nn_recv(pair_socket, buf1, 256, 0);
if (rc < 0) {
printf("nn_recv failed! error: %s.rc = %d.\n", nn_err_strerror(errno), rc);
}
//打印
printf("recv:%s\n", buf1);
memset(buf1, 0, 256);
//Sleep(1000);
//关闭套接字
rc = nn_shutdown(pair_socket, 1);
if (rc != 1) {
printf("nn_close failed! error: %s.\n", nn_err_strerror(errno));
//system("pause");
nn_err_abort();
//return 0;
}
std::cout << "testtttttttttttttttttttttttttttttttttt "
<< "hostnameeeeeeeeeeeeeeeeeeeeeeeeeeeeee:" << lease->hostname_ << std::endl;
std::cout << "testtttttttttttttttttttttttttttttttttt "
<< "ipppppppppppppppppppppppppppppppppppp:" << lease->addr_.toText() << std::endl;
std::cout << "lease ALLOC " << __LINE__ << " file name " << __FILE__
<< " HOST:" << lease->hostname_ << std::endl;
std::cout << "lease ALLOC " << __LINE__ << " file name " << __FILE__
<< " IP:" << lease->addr_.toText() << std::endl;
}
It sounds like you need some general information on the KEA software developed by Internet Systems Consortium aka: https://kea.isc.org/ I would read through the Kea docs, mailing lists and the general development wiki to try to hone in on the specific issue you are having with your code. Once you are able explain the issue you are having with your code you can edit your question with your details, and there is a much better chance that you will get more meaningful answers from this site.
I want to record a video from a V4L2 device (from the Raspberry Pi camera) in C.
The recording itself works and I can save the video to a file.
However I need to change the bitrate of the video. From the strace output of the v4l2-ctl --set-ctrl video_bitrate=10000000 command I know that the extended controls API of v4l2 is used to achieve this.
Here's my code which doesn't work so far:
#include <iostream>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h> //mmap
#include <fcntl.h>
#include <unistd.h>
#include <linux/videodev2.h>
using namespace std;
#define numbuffers 3
struct picturebuffer
{
void *startadress;
size_t length;
};
//array in which the buffer pointer are being stored
picturebuffer pb[numbuffers];
int main()
{
//open camera
int fd;
fd = open("/dev/video0", O_RDWR);
if(fd < 0)
{
cout << "error during opening the camera device!";
cout.flush();
}
cout << "camera opened";
//read capabilities
struct v4l2_capability caps;
if(ioctl(fd, VIDIOC_QUERYCAP, &caps) < 0)
{
cout << "error while reading the capabilities!";
cout.flush();
}
cout << "Capabilities " << caps.capabilities << endl;
//ToDo: check for required capabilities
//set image data
struct v4l2_format format;
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
format.fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
format.fmt.pix.width = 1920;
format.fmt.pix.height = 1080;
if(ioctl(fd, VIDIOC_S_FMT, &format) < 0)
{
cout << "error in the image format";
}
cout << "Image properties set" << endl;
//Todo: check if width and height fit together (VIDIOC_ENUM_FRAMESIZES)
//set extended Controls
struct v4l2_ext_controls ecs;
struct v4l2_ext_control ec;
memset(&ecs, 0, sizeof(ecs));
memset(&ec, 0, sizeof(ec));
ec.id = V4L2_CID_MPEG_VIDEO_BITRATE;
ec.value = 10000000;
ec.size = 0;
ecs.controls = &ec;
ecs.count = 1;
ecs.ctrl_class = V4L2_CTRL_CLASS_MPEG;
if(ioctl(fd, VIDIOC_S_EXT_CTRLS, &ecs) < 0)
{
cout << "error in extended controls bitrate";
cout.flush();
}
//allocate buffer in the kernel
struct v4l2_requestbuffers req;
req.count = numbuffers;
req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory = V4L2_MEMORY_MMAP;
if(ioctl(fd, VIDIOC_REQBUFS, &req) < 0)
{
cout << "errro while allocating buffer";
cout.flush();
}
cout << "number of buffers: " << req.count << endl;
cout.flush();
//map buffers into userspace
for(int i=0; i<numbuffers; i++)
{
struct v4l2_buffer bufferinfo;
memset(&bufferinfo, 0, sizeof(bufferinfo));
bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufferinfo.memory = V4L2_MEMORY_MMAP;
bufferinfo.index = i;
if(ioctl(fd, VIDIOC_QUERYBUF, &bufferinfo) < 0)
{
cout << "error while querying bufferinfo";
cout.flush();
}
pb[i].startadress = mmap(NULL, bufferinfo.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, bufferinfo.m.offset);
pb[i].length = bufferinfo.length;
if(pb[i].startadress == MAP_FAILED)
{
cout << "error during mmap" << endl;
}
memset(pb[i].startadress, 0, bufferinfo.length);
cout << "size of buffer: " << bufferinfo.length << endl;
}
cout << "buffers mapped into userspace" << endl;
cout.flush();
//queue in the buffers
for(int i=0; i<numbuffers; i++)
{
struct v4l2_buffer bufferinfo;
memset(&bufferinfo, 0, sizeof(bufferinfo));
bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufferinfo.memory = V4L2_MEMORY_MMAP;
bufferinfo.index = i;
if(ioctl(fd, VIDIOC_QBUF, &bufferinfo) < 0)
{
cout << "error while queueing the buffers in" << endl;
}
}
//since that point the driver starts capturing the pics
int type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(ioctl(fd, VIDIOC_STREAMON, &type) < 0)
{
cout << "error while starting the stream" << endl;
}
int file;
if((file = open("/home/pi/image.h264", O_WRONLY | O_CREAT, 0660)) < 0)
{
cout << "error while writing the file";
}
//loop for managing the pics
for(int i=0; i<100; i++)
{
struct v4l2_buffer bufferinfo;
memset(&bufferinfo, 0, sizeof(bufferinfo));
bufferinfo.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
bufferinfo.memory = V4L2_MEMORY_MMAP;
if(ioctl(fd, VIDIOC_DQBUF, &bufferinfo) < 0)
{
cout << "error while getting the buffer!" << endl;
}
//do anything with the pic
char buf[pb[bufferinfo.index].length];
memcpy(&buf, pb[bufferinfo.index].startadress, pb[bufferinfo.index].length);
cout << bufferinfo.index << endl;
cout.flush();
//write picture into the file
write(file, pb[bufferinfo.index].startadress, pb[bufferinfo.index].length);
if(ioctl(fd, VIDIOC_QBUF, &bufferinfo) < 0)
{
cout << "error while enqueuing the buffer" << endl;
}
}
close(file);
if(ioctl(fd, VIDIOC_STREAMOFF, &type) < 0)
{
cout << "error while stopping the stream" << endl;
}
//clean up
for(int i=0; i<numbuffers; i++)
{
if(munmap(pb[i].startadress, pb[i].length) < 0)
{
cout << "error during unmap";
}
}
//close camera file
close(fd);
cout << "!!!Hello World!!!" << endl;
cout.flush();
return 0;
}
The ioctl call seems to succeed, however my output file always has the same size as of 199,2 MB. Does someone know what´s wrong in the code ?
You need to check if the camera driver supports that IOCTL command. If the driver doesn't support the IOCTL command by not implementing it, you still can execute the command and it is routed to v4l2 default implementation, no actual changes are applied to the camera setting
Try to change the lines:
pb[bufferinfo.index].length
By:
pb[bufferinfo.index].bytesused
For example:
write(file, pb[bufferinfo.index].startadress, pb[bufferinfo.index].bytesused);
I can't get libbz2 to work. After 10 000 characters it terminates with end of stream although the input file contains several gigabytes. I just cannot figure out what goes wrong. Thank you for any remarks.
Here is my code:
string read_bz2_file(const string& filename) {
string result;
FILE* f;
BZFILE* b;
const int BUFSIZE = 1000;
char buf[BUFSIZE];
int bzerror;
f = fopen(filename.c_str(), "r");
if (!f) {
/* handle error */
cerr << "cannot read file " << filename << endl;
return "";
}
b = BZ2_bzReadOpen(&bzerror, f, 0, 0, NULL, 0);
if (bzerror != BZ_OK) {
BZ2_bzReadClose(&bzerror, b);
cerr << "cannot read file " << filename << endl;
return "";
/* handle error */
}
bzerror = BZ_OK;
while (bzerror == BZ_OK /* arbitrary other conditions */) {
BZ2_bzRead(&bzerror, b, buf, BUFSIZE /* size of buf */);
cout << "bzerror: " << bzerror << endl;
if (bzerror == BZ_OK) {
/* do something with buf[0 .. nBuf-1] */
result.append(buf);
}
}
if (bzerror != BZ_STREAM_END) {
BZ2_bzReadClose(&bzerror, b);
cerr << "error while reading file " << filename << endl;
return "";
/* handle error */
} else {
result.append(buf);
BZ2_bzReadClose(&bzerror, b);
return result;
}
return result;
}
You can try to open the file in binary mode, adding a "b" to the fopen mode:
f = fopen(filename.c_str(), "rb");
I am just try to write simple program for some practice. But iTunes COM for Windows SDK threw me a little surprise.
I am want to create playlist and add file to it but when i call IITUserPlaylist::AddFile program crash with access violation. I can all other methods like Delete etc.
Project (MSVC10): http://www76.zippyshare.com/v/34795637/file.html
#include <iostream>
#include <windows.h>
#include <comutil.h>
#include "iTunesCOMInterface.h"
int main(int argc, char* argv[])
{
CoInitialize(0);
HRESULT hRes;
IiTunes* itunes = 0;
// note - CLSID_iTunesApp and IID_IiTunes are defined in iTunesCOMInterface_i.c
hRes = ::CoCreateInstance(CLSID_iTunesApp, NULL, CLSCTX_LOCAL_SERVER, IID_IiTunes, (PVOID *)&itunes);
if(hRes != S_OK && itunes == nullptr)
{
std::cout << "Can not create iTunesApp instance" << std::endl;
CoUninitialize();
return 1;
}
IITLibraryPlaylist* mainLibrary = 0;
hRes = itunes->get_LibraryPlaylist(&mainLibrary);
if(hRes != S_OK || mainLibrary == 0)
{
std::cout << "Can not get main library" << std::endl;
itunes->Release();
CoUninitialize();
return 1;
}
IITSource* mainLibrarySource = 0;
hRes = itunes->get_LibrarySource(&mainLibrarySource);
if(hRes != S_OK || mainLibrarySource == 0)
{
std::cout << "Can not get library source" << std::endl;
mainLibrary->Release();
itunes->Release();
CoUninitialize();
return 1;
}
IITPlaylistCollection* playlistCollection = 0;
hRes = mainLibrarySource->get_Playlists(&playlistCollection);
if(hRes != S_OK || playlistCollection == 0)
{
std::cout << "Can not get source playlists" << std::endl;
mainLibrarySource->Release();
mainLibrary->Release();
itunes->Release();
CoUninitialize();
return 1;
}
BSTR playlistName = SysAllocString(L"SoundFrost playlist");
IITPlaylist* ownPlaylist = 0;
//TODO: But there can be additional playlists with the same name, since playlist names are not unique
hRes = playlistCollection->get_ItemByName(playlistName, &ownPlaylist);
if(hRes != S_OK || ownPlaylist == 0)
{
//just create new
hRes = itunes->CreatePlaylist(playlistName, &ownPlaylist);
if(hRes != S_OK || ownPlaylist == 0)
{
std::cout << "Can not create playlist";
SysFreeString(playlistName);
playlistCollection->Release();
mainLibrarySource->Release();
mainLibrary->Release();
itunes->Release();
CoUninitialize();
return 1;
}
}
SysFreeString(playlistName);
ITPlaylistKind playlistKind;
hRes = ownPlaylist->get_Kind(&playlistKind);
if(hRes == S_OK && playlistKind == ITPlaylistKindUser)
{
IITUserPlaylist* ownUserPlaylist = static_cast<IITUserPlaylist*>(ownPlaylist);
if(ownUserPlaylist != 0)
{
BSTR filePath = SysAllocString(L"C:\\test.mp3");
IITOperationStatus* status;
//hRes = mainLibrary->AddFile(filePath, &status);
//hRes = ownUserPlaylist->AddFile(filePath, &status);
SysFreeString(filePath);
}
}
playlistCollection->Release();
ownPlaylist->Release();
mainLibrarySource->Release();
mainLibrary->Release();
itunes->Release();
CoUninitialize();
return 0;
}
If i call IITLibraryPlaylist::AddFile all was right.
Just uncomment 95 or 96 line for test.
Simple C# code works fine:
iTunesApp itunes = new iTunesLib.iTunesApp();
IITUserPlaylist playlist = itunes.CreatePlaylist("C# playlist") as IITUserPlaylist;
IITOperationStatus status = playlist.AddFile("C:\\test.mp3");
I can not understand why this is happening.
You can't really do this with COM:
IITUserPlaylist* ownUserPlaylist = static_cast<IITUserPlaylist*>(ownPlaylist);
You're just casting an interface pointer into another interface pointer. You must do a QueryInterface instead:
HRESULT hr = ownPlaylist->QueryInterface(IID_IITUserPlaylist, (void**)&ownUserPlaylist);