How to get GPS data? emulator always returns runtime GPS disabled on Tizen native - gps

I am trying to access GPS data on Tizen native app. I have turned on location asked permissions, privileges, and granted permission on emulator. But when I run code to access location information, it gets zero values. For runtime location info it gets GPS Disabled equivalent return. I need to access current injected location on emulator.
Sample code to check GPS status:
retCheck = runtime_info_get_value_int(RUNTIME_INFO_KEY_GPS_STATUS,
&value_int);
if (retCheck != RUNTIME_INFO_ERROR_NONE) {
dlog_print(DLOG_ERROR, LOG_TAG, "runtime_info_get_value_int error: %d",
retCheck);
snprintf(chars, sizeof(chars),
"<br>runtime_info_get_value_int error: %d", retCheck);
strcat(str, chars);
return;
} else {
switch (value_int) {
case RUNTIME_INFO_GPS_STATUS_DISABLED:
dlog_print(DLOG_DEBUG, LOG_TAG, "GPS status: DISABLED.");
snprintf(chars, sizeof(chars), "<br>GPS status: DISABLED.");
strcat(str, chars);
break;
case RUNTIME_INFO_GPS_STATUS_SEARCHING:
dlog_print(DLOG_DEBUG, LOG_TAG, "GPS status: SEARCHING.");
snprintf(chars, sizeof(chars), "<br>GPS status: SEARCHING.");
strcat(str, chars);
break;
case RUNTIME_INFO_GPS_STATUS_CONNECTED:
dlog_print(DLOG_DEBUG, LOG_TAG, "GPS status: CONNECTED.");
snprintf(chars, sizeof(chars), "<br>GPS status: CONNECTED.");
strcat(str, chars);
break;
default:
dlog_print(DLOG_DEBUG, LOG_TAG, "GPS status: Unknown.");
snprintf(chars, sizeof(chars), "<br>GPS status: Unknown.");
strcat(str, chars);
break;
}
Here it is returning Serarching.
Sample code for gps location info:
//init location manager with gps type.
location_manager_get_location(gps, &altitude, &latitude, &longitude, &climb,
&direction, &speed, &level, &horizontal, &vertical, &timestamp);
snprintf(chars, sizeof(chars),
"<br>In GPS: altitude %f, latitude %f, longitude %f, climb %f, direction %f, speed %f, horizontal %f, vertical %f",
altitude, latitude, longitude, climb, direction, speed, horizontal,
vertical);
Here all values are 0.
What to do to get GPS data?
Edit solution: It has to retrieve information on location manager callback.

Make sure your GPS is enabled (manually enable in emulator settings->Location->GPS).
May be this article will help you for more information on location https://docs.tizen.org/application/native/guides/location-sensors/location
Check this Privilege too(http://tizen.org/privilege/location).
There seems to be problem in enabling GPS, we cannot get location values in GPS disabled state.

Related

Arduino - Trouble reading sensor data from Venus GPS and MS5803-14BA Pressure Sensor to Arduino Uno

I'm trying to get GPS and pressure readings from my Arduino Uno. However, when I try to get pressure/temperature readings off of the pressure sensor (code snippet below), the GPS starts sending malformed packets to my serial monitor. I'd like to be able to get good GPS and pressure readings from my Arduino. (Hardware details provided below)
float temperature_c, temperature_f;
double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;
String dataString = "";
pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}
Here's the full code:
#include <SoftwareSerial.h>
//pressure sensor libraries
#include <Wire.h>
#include <SparkFun_MS5803_I2C.h>
//datalogger library
#include <SPI.h>
#include <SD.h>
// set up datalogger
const int chipSelect = 4;
/*-----------GPS-----------*/
SoftwareSerial gpsSerial(10, 11); // RX, TX (TX not used)
const int sentenceSize = 80;
// the $GPGGA, $GPGSA, etc. are sentences and are sent 1 character at a time from the GPS
char sentence[sentenceSize];
/*------------Pressure sensor-------*/
// Begin class with selected address
// available addresses (selected by jumper on board)
// default is ADDRESS_HIGH
// ADDRESS_HIGH = 0x76
// ADDRESS_LOW = 0x77
MS5803 sensor(ADDRESS_HIGH);
// Create Variable to store altitude in (m) for calculations;
double pressure_baseline;
double base_altitude = 1655.0; // Altitude of SparkFun's HQ in Boulder, CO. in (m)
void setup()
{
Serial.begin(9600);
gpsSerial.begin(9600);
/*----------Pressure sensor stuff----------*/
Serial.println("\ntemperature (C), temperature (F), pressure (abs), pressure (relative), change in altitude");
//Retrieve calibration constants for conversion math.
sensor.reset();
sensor.begin();
pressure_baseline = sensor.getPressure(ADC_4096);
Serial.println(pressure_baseline);
Serial.println("\n");
}
void loop()
{
static int i = 0;
if (gpsSerial.available())
{
// Serial.print("GPS Serial is available\n");
char ch = gpsSerial.read();
if (ch != '\n' && i < sentenceSize)
{
sentence[i] = ch;
i++;
}
else
{
sentence[i] = '\0';
i = 0;
// Serial.println("\n");
Serial.println(sentence);
// Serial.println("\n");
displayGPS();
}
}
/*----------------------PRESSURE SENSOR-------------------------*/
float temperature_c, temperature_f;
double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;
String dataString = "";
pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}
/*--------------------------Pressure sensor methods----------------*/
// Thanks to Mike Grusin for letting me borrow the functions below from
// the BMP180 example code.
double sealevel(double P, double A)
// Given a pressure P (mbar) taken at a specific altitude (meters),
// return the equivalent pressure (mbar) at sea level.
// This produces pressure readings that can be used for weather measurements.
{
return(P/pow(1-(A/44330.0),5.255));
}
double altitude(double P, double P0)
// Given a pressure measurement P (mbar) and the pressure at a baseline P0 (mbar),
// return altitude (meters) above baseline.
{
return(44330.0*(1-pow(P/P0,1/5.255)));
}
void displayGPS()
{
char field[20];
getField(field, 0);
if (strcmp(field, "$GPGGA") == 0)
{
Serial.print("Lat: ");
getField(field, 2); // number
Serial.print(field);
getField(field, 3); // N/S
Serial.print(field);
Serial.print(" Long: ");
getField(field, 4); // number
Serial.print(field);
getField(field, 5); // E/W
Serial.println(field);
Serial.print("Altitude: ");
getField(field, 9);
Serial.println(field);
Serial.print("Number of satellites: ");
getField(field, 7);
Serial.println(field);
Serial.println("-----------------------\n");
}
}
void getField(char* buffer, int index)
{
int sentencePos = 0;
int fieldPos = 0;
int commaCount = 0;
while (sentencePos < sentenceSize)
{
if (sentence[sentencePos] == ',')
{
commaCount ++;
sentencePos ++;
}
if (commaCount == index)
{
buffer[fieldPos] = sentence[sentencePos];
fieldPos ++;
}
sentencePos ++;
}
buffer[fieldPos] = '\0';
}
When the line to get pressure is commented like so...
float temperature_c, temperature_f;
double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;
String dataString = "";
// pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}
...my GPS gives me proper packets of data:
$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
$GPRMC,120208.000,V,24006,,,N*71
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02
$GPGGA,120209.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*61
Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------
$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
$GPRMC,120209.000,V,24006,,,N*70
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02
$GPGGA,120210.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*69
Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------
$GPGSA,A,1,,,,,,,,,,,,,0.0,0.0,0.0*30
$GPRMC,120210.000,V,240006,,,N*78
$GPVTG,000.0,T,,M,000.0,N,000.0,K,N*02
$GPGGA,120211.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,0000*68
Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------
But when my line to get pressure is uncommented...
float temperature_c, temperature_f;
double pressure_abs, pressure_relative, altitude_delta, pressure_baseline;
String dataString = "";
pressure_abs = sensor.getPressure(ADC_4096); //IF THIS LINE REMOVED, GPS SENDS GOOD DATA.
}
My GPS packets become malformed:
$GPGGA,120125.000,2400.0000,N,12100.0000,E,0,00,0.0,0.0,M,0.0,M,,$0,0T,$GPGGA,12
Lat: 2400.0000N Long: 12100.0000E
Altitude: 0.0
Number of satellites: 00
-----------------------
126.000,2400.0000,N,120,00..
$GPGGA,120127.000,2400.0000,N,100,$GPGGA,120128.000,2400.0000,N,1200,20*0$GPGGA,
Lat: 2400.0000N Long: 100$GPGGA
Altitude: 1200
Number of satellites: 2400.0000
-----------------------
20129.000,2400.0000,N,120G.4,,*$GPGGA,120130.000,2400.0000,N,1060$GPGGA,120131.0
0,2400.0000,N,12,*..E
0$GPGGA,120132.000,2400.0000,N,120A00.0
$GPGGA,120133.000,2400.0000,N,1M,
0,,$GPGGA,120134.000,2400.0000,N,1200,1070$GPGGA,120135.000,2400.0000,N,10,,,0,0
GPGGA,120136.000,2400.0000,N,120G0,0V,$GPGGA,120137.000,2400.0000,N,1,,30000
$GP
GA,120138.000,2400.0000,N,0G00V0VK$GPGGA,120139.000,2400.0000,N1,,VP,6,$GPGGA,12
140.000,2400.0000,N,1.,0*.0.
$GPGGA,120141.000,2400.0000,N,0A*00*N$GPGGA,120142.000,2400.0000,N,.,,110,0$GPGG
Lat: 2400.0000N Long: 0A*00*N$GPGGA120142.000
Altitude: ,110
Number of satellites: N
-----------------------
,120143.000,2400.0000,N,1,,P$02,$GPGGA,120144.000,2400.0000,N,10.0$GPGGA,120145.
00,2400.0000,N,10A*00000$GPGGA,120146.000,2400.0000,N,0G.020,*$GPGGA,120147.000,
400.0000,N0,,20,0$GPGGA,120148.000,2400.0000,N,120P,,0P,$GPGGA,120149.000,2400.0
00,N,1.S0000*$GPGGA,120150.000,2400.0000,N,1.,,,0,0$GPGGA,120151.000,2400.0000,N
100,50E,$GPGGA,120152.000,2400.0000,N,120S.00,N$GPGGA,120153.000,2400.0000,N,1.A
0002$GPGGA,120154.000,2400.0000,N,1.,,00N,$GPGGA,120155.000,2400.0000,N,1E*..0A0
GPGGA,120156.000,2400.0000,N,120S0400N$GPGGA,120157.000,2400.0000,N,1.A0.000$GPG
A,120158.000,2400.0000,N,100,2.N.$GPGGA,120159.000,2400.0000,N,100,906,$GPGGA,12
200.000,2400.0000,N,120,*000*$GPGGA,120201.000,2400.0000,N,10,,,.GN$GPGGA,120202
000,2400.0000,N,11,,C160$GPGGA,120203.000,2400.0000,N,12,6.00
,$GPGGA,120204.000
2400.0000,N,100,00*,$GPGGA,120205.000,2400.0000,N,120,300.
$GPGGA,120206.000,2400.0000,N,1.,R,0M$GPGGA,120207.000,2400.0000,N,12,00007N$GPG
Lat: 2400.0000N Long: 1.R
Altitude: N
Number of satellites: 120207.000
-----------------------
A,120208.000,2400.0000,N,12,A*000
$GPGGA,120209.000,2400.0000,N,007,$GPGGA,12021
.000,2400.0000,N,12,A*.00
$GPGGA,120211.000,2400.0000,N,10,,20N2$GPGGA,120212.00
,2400.0000,N,100,20N0$GPGGA,120213.000,2400.0000,N,120G040GN$GPGGA,120214.000,24
0.0000,N,1,,3.002$GPGGA,120215.000,2400.0000,N,1.,,,160$GPGGA,120216.000,2400.00
0,N,100,2.N,$GPGGA,120217.000,2400.0000,N,12,G0V.TK$GPGGA,120218.000,2400.0000,N
10G04,,0$GPGGA,120219.000,2400.0000,N,10,,10,0$GPGGA,120220.000,2400.0000,N,1,*,
0BN$GPGGA,120221.000,2400.0000,N,120S00002$GPGGA,120222.000,2400.0000,N,1M,
0,T$GPGGA,120223.000,2400.0000,N,1200,208N$GPGGA,120224.000,2400.0000,N,100,2.N,
GPGGA,120225.000,2400.0000,N,120G02.TN$GPGGA,120226.000,2400.0000,N,10,0000*$GPG
A,120227.000,2400.0000,N,1.,,00,,$GPGGA,120228.000,2400.0000,N,1E6..03,$GPGGA,12
229.000,2400.0000,N,12,,*0000$GPGGA,120230.000,2400.0000,N,1.,,0000$GPGGA,120231
000,2400.0000,N,100,2.,0$GPGGA,120232.000,2400.0000,N,12.S0000*$GPGGA,120233.000
2400.0000,N,1.S.20TK$GPGGA,120234.000,2400.0000,N,12M,$N0M$GPGGA,120235.000,2400
0000,N,10M,C160$GPGGA,120236.000,2400.0000,N,12,$.,0G0$GPGGA,120237.000,2400.000
,N,1,P,,0G,$GPGGA,120238.000,2400.0000,N,10,,C100$GPGGA,120239.000,2400.0000,N,1
,,C1,0$GPGGA,120240.000,2400.0000,N,12,G,2.G,$GPGGA,120241.000,2400.0000,N,10A00
0
$GPGGA,120242.000,2400.0000,N,1.,,00*N$GPGGA,120243.000,2400.0000,N,1,*0.,
0$G
GGA,120244.000,2400.0000,N,120A00000$GPGGA,120245.000,2400.0000,N,10,
0,,$GPGGA,120246.000,2400.0000,N,1200,407N$GPGGA,120247.000,2400.0000,N,12,,R16M
GPGGA,120248.000,2400.0000,N,1200,80
0$GPGGA,120249.000,2400.0000,N,10
,00,$.$GP
GA,120250.000,2400.0000,N,0,,1C1,0$GPGGA,120251.000,2400.0000,N,.S0,4,,*$GPGGA,1
0252.000,2400.0000,N,0
000,G0$GPGGA,120253.000,2400.0000,N,00,,.0.
$GPGGA,120254.000,2400.0000,N,,A*00002$GPGGA,120255.000,2400.0000,N,0A*00002$GPG
Lat: 2400.0000N Long: ,A*00002$GPGGA120255.000
Altitude:
Number of satellites: N
-----------------------
Hardware:
Arduino board: Arduino Uno R3
GPS: Venus GPS (made by Sparkfun)
Pressure sensor: Ms5803-14BA Breakout (made by Sparkfun)
Data logger: OpenLog (made by Sparkfun)
Setup
What's causing my GPS to send bad packets? Evidently, the pressure sensor is somehow interfering with the GPS, but how is it doing that and how can I avoid interference?
What's causing my GPS to send bad packets?
Well, the GPS is sending good packets, but the Arduino is too busy doing other things (pressure library) to watch the GPS characters come in. It's all because SoftwareSerial is a CPU hog. Other libraries, like AltSoftSerial (works on fewer pins), or the recent gSoftSerial would be better choices.
Do you really need to receive GPS while you're getting a pressure reading? Why not read GPS for two seconds to get a fix, then stop it and get the pressure reading. Stop the pressure interface and start the GPS again. Rinse and repeat.
I'll also throw in my obligatory pitch for NeoGPS. If nothing else, the examples show a different program structure that would help immensely... you may be able to take the pressure reading during the GPS quiet time, without stopping and starting the GPS and pressure interfaces.
NeoGPS also parses the characters as they are received, so you don't have to buffer the sentence. BTW, I recommend staying away from String, like many developers.
Edit to add: I just published NeoSWSerial, an alternative to SoftwareSerial that is much more reliable and uses much less CPU time. If the Input Capture pin 8 (and pin 9 for TX) is a possibility for you to use, you might consider NeoICSerial. They're both on github near NeoGPS.

GStreamer demo deosn't work in Virtual Machine (seeking simple example)

I am tryign to code an extremely simple GStreamer app. It doesn't matter what it does, so long as GStreamer does something. Even just displaying some text or a simple JPEG would be fine.
Below is about the best example that I could find by Googling (I have added a few error checks). When I run it in a Linux Virtual Machine running under Windows, I see this console message:
libEGL warning: pci id for fd 4: 80ee:beef, driver (null)
libEGL warning: DRI2: failed to open vboxvideo (search paths
/usr/lib/i386-linux-gnu/dri:${ORIGIN}/dri:/usr/lib/dri)
Googling indicates that this is an error with 3D rendering inside a virtual machine. I can find no solution.
So, can someone fix the code below so that it will run in a VM? I assume that that would mean avoiding 3D rendering, so maybe display an image or some text? It is not necessary to play video, this is just a simple proof of concept of using GStreamer inside something else (which has to be running in a VM).
Here's the code ...
void GstreamerPlayVideo()
{
GstElement *pipeline;
GstBus *bus;
GstMessage *msg;
int argc;
GError *error = NULL;
/* Initialize GStreamer */
if (gst_init_check(&argc, NULL, &error) == TRUE)
{
/* Build the pipeline */
// Change URL to test failure
pipeline = gst_parse_launch ("bin uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", &error);
//// pipeline = gst_parse_launch ("bin uri=http://tecfa.unige.ch/guides/x3d/www.web3d.org/x3d/content/examples/HelloWorld.gif", &error);
if (pipeline != NULL)
{
/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);
/* wait until it's up and running or failed */
if (gst_element_get_state (pipeline, NULL, NULL, -1) == GST_STATE_CHANGE_FAILURE)
{
g_error ("GST failed to go into PLAYING state");
exit(1);
}
/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
if (bus != NULL)
{
msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
/* Parse message */
if (msg != NULL)
{
gchar *debug_info;
switch (GST_MESSAGE_TYPE (msg))
{
case GST_MESSAGE_ERROR:
gst_message_parse_error (msg, &error, &debug_info);
g_printerr ("Error received from element %s: %s\n", GST_OBJECT_NAME (msg->src), error->message);
g_printerr ("Debugging information: %s\n", debug_info ? debug_info : "none");
g_clear_error (&error);
g_free (debug_info);
break;
case GST_MESSAGE_EOS:
g_print ("End-Of-Stream reached.\n");
break;
default:
/* We should not reach here because we only asked for ERRORs and EOS */
g_printerr ("Unexpected message received.\n");
break;
}
gst_message_unref (msg);
}
/* Free resources */
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
}
else
{
g_print ("GST get bus error: %s\n", error->message);
exit(1);
}
}
else
{
g_print ("GST parse error: %s\n", error->message);
exit(1);
}
}
else
{
g_print ("GST init error: %s\n", error->message);
exit(1);
}
} // GstreamerPlayVideo()
Try specifying a video sink by hand in your pipeline.
videotestsrc ! ximagesink
Your system may have an EGL video sink plugin installed as the primary video plugin. ximagesink seems a little more likely to work.
Like this:
//this line is where you're creating your pipeline
pipeline = gst_parse_launch ("videotestsrc ! ximagesink", &error);
I recommend experimenting with the gst-launch command first so you can get a hang of pipeline syntax, what sinks and sources are, etc. The simplest test you can run is something like this (if you have gstreamer 1.0 installed, you may have 0.10), from the command line:
gst-launch-1.0 videotestsrc ! autovideosink

Rendering QCRenderer for displaying onto DeckLink Cards

I'm writing an application in xcode on a MacMini (Late 2012).
It's an app where I load some QuartzComposer files (with QCRenderer class). Then render those files into videomemory and read them back using glReadPixels to get all the pixel data. This pixel data is then pushed to a decklink frame (I'm using BlackMagic Decklink SDK) for playback onto a DeckLink Quad. Everything is working great. It's even possible to render 3 outputs without dropping frames on HD (1080i50). But after a while (like 5 mins) it is dropping frames even when I'm only rendering 1 output.
So I think there are 2 possible reasons. First. When there is a completed frame (frame dit played out) callback I'm receiving the bmdOutputFrameDisplayedLate from the SDK which means the frame was not played at the time it was scheduled for. So when this happens I'm pushing the next frame by 1 into the future.
Second. I've set a frameBuffer Size (3 frames are rendered out before playback will be started). So maybe after a while rendering is falling behind the scheduling which will cause the dropping/late frames. Maybe i'm not doing the openGL rendering process like it should be?
So here's my code:
-> first I'm loading a QCRenderer into memory
- (id)initWithPath:(NSString*)path forResolution:(NSSize)resolution
{
if (self = [super init])
{
NSOpenGLPixelFormatAttribute attributes[] = {
NSOpenGLPFAPixelBuffer,
NSOpenGLPFANoRecovery,
NSOpenGLPFAAccelerated,
NSOpenGLPFADepthSize, 24,
(NSOpenGLPixelFormatAttribute) 0
};
NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
quartzPixelBuffer = nil;
quartzPixelBuffer = [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:GL_TEXTURE_2D textureInternalFormat:GL_RGBA textureMaxMipMapLevel:0 pixelsWide:resolution.width pixelsHigh:resolution.height];
if(quartzPixelBuffer == nil)
{
NSLog(#"Cannot create OpenGL pixel buffer");
}
//Create the OpenGL context to render with (with color and depth buffers)
quartzOpenGLContext = [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil];
if(quartzOpenGLContext == nil)
{
NSLog(#"Cannot create OpenGL context");
}
[quartzOpenGLContext setPixelBuffer:quartzPixelBuffer cubeMapFace:0 mipMapLevel:0 currentVirtualScreen:[quartzOpenGLContext currentVirtualScreen]];
//Create the QuartzComposer Renderer with that OpenGL context and the specified composition file
NSString* correctPath = [path substringWithRange:NSMakeRange(0, path.length - 1)];
quartzRenderer = [[QCRenderer alloc] initWithOpenGLContext:quartzOpenGLContext pixelFormat:format file:correctPath];
if(quartzRenderer == nil)
{
NSLog(#"Cannot create QCRenderer");
}
}
return self;
}
-> next step is to render 3 frames (BUFFER_DEPTH is set to 3 currently) before starting playback
- (void) preRollFrames;
{
// reset scheduled
[self resetScheduled];
totalFramesScheduled = 0;
if (isRunning == TRUE)
{
[self stopPlayback];
}
#autoreleasepool
{
for (double i = 0.0; i < ((1.0 / framesPerSecond) * BUFFER_DEPTH); i += 1.0/framesPerSecond)
{
// render image at given time
[self createVideoFrame:TRUE];
}
}
}
-> this is the createVideoFrame function. When scheduleBlack is set to true there must be rendered a black frame. If false the function renderFrameAtTime for the QCRenderer class is called. The return of this function is then passed to the decklinkVideoFrame object. Next, this frame will be pushed into the schedule queue of the DeckLink Card (SDK).
- (void) createVideoFrame:(BOOL)schedule
{
#autoreleasepool
{
// get displaymode
IDeckLinkDisplayMode* decklinkdisplaymode = (IDeckLinkDisplayMode*)CurrentRes;
// create new videoframe on output
if (deckLinkOutput->CreateVideoFrame((int)decklinkdisplaymode->GetWidth(), (int)decklinkdisplaymode->GetHeight(), (int)decklinkdisplaymode->GetWidth() * 4, bmdFormat8BitARGB, bmdFrameFlagFlipVertical, &videoFrame) != S_OK)
{
// failed to create new video frame on output
// display terminal message
sendMessageToTerminal = [[mogiTerminalMessage alloc] initWithSendNotification:#"terminalErrorMessage" forMessage:[NSString stringWithFormat:#"DeckLink: Output %d -> Failed to create new videoframe", outputID]];
}
unsigned frameBufferRowBytes = ((int)decklinkdisplaymode->GetWidth() * 4 + 63) & ~63;
void* frameBufferPtr = valloc((int)decklinkdisplaymode->GetHeight() * frameBufferRowBytes);
// set videoframe pointer
if (videoFrame != NULL)
{
videoFrame->GetBytes((void**)&frameBufferPtr);
}
// fill pointer with pixel data
if (scheduleBlack == TRUE)
{
[qClear renderFrameAtTime:1.0 forBuffer:(void**)frameBufferPtr forScreen:0];
// render first frame qRenderer
if (qRender != NULL)
{
[qRender renderFirstFrame];
}
}
else
{
[qRender renderFrameAtTime:totalSecondsScheduled forBuffer:(void**)frameBufferPtr forScreen:screenID];
schedule = TRUE;
}
// if playback -> schedule frame
if (schedule == TRUE)
{
// schedule frame
if (videoFrame != NULL)
{
if (deckLinkOutput->ScheduleVideoFrame(videoFrame, (totalFramesScheduled * frameDuration), frameDuration, frameTimescale) != S_OK)
{
// failed to schedule new frame
// display message to terminal
sendMessageToTerminal = [[mogiTerminalMessage alloc] initWithSendNotification:#"terminalErrorMessage" forMessage:[NSString stringWithFormat:#"DeckLink: Output %d -> Failed to schedule new videoframe", outputID]];
}
else
{
// increase totalFramesScheduled
totalFramesScheduled ++;
// increase totalSecondsScheduled
totalSecondsScheduled += 1.0/framesPerSecond;
}
// clear videoframe
videoFrame->Release();
videoFrame = NULL;
}
}
}
}
-> render frameAtTime function from QCRenderer class
- (void) renderFrameAtTime:(double)time forBuffer:(void*)frameBuffer forScreen:(int)screen
{
#autoreleasepool
{
CGLContextObj cgl_ctx = [quartzOpenGLContext CGLContextObj];
// render frame at time
[quartzRenderer renderAtTime:time arguments:NULL];
glReadPixels(0, 0, [quartzPixelBuffer pixelsWide], [quartzPixelBuffer pixelsHigh], GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, frameBuffer);
}
}
-> After perolling frames Playback is started. Each time there's a frame played out. This Callback method is called (Decklink SDK). If there's a late frame. I'm pushing the totalFrames 1 frame into future.
PlaybackDelegate::PlaybackDelegate (DecklinkDevice* owner)
{
pDecklinkDevice = owner;
}
HRESULT PlaybackDelegate::ScheduledFrameCompleted (IDeckLinkVideoFrame* completedFrame, BMDOutputFrameCompletionResult result)
{
if (result == bmdOutputFrameDisplayedLate)
{
// if displayed late bump scheduled time further into the future by one frame
[pDecklinkDevice increaseScheduledFrames];
NSLog(#"bumped %d", [pDecklinkDevice getOutputID]);
}
if ([pDecklinkDevice getIsRunning] == TRUE)
{
[pDecklinkDevice createVideoFrame:TRUE];
}
return S_OK;
}
So my question. Am I doing the openGL rendering process correct? Maybe that is causing the delay after some minutes. Or I'm a handling the displayedLate frame incorrect so the timing of the scheduling queue is messed up after some time?
Thx!
Thomas
When late, try advancing the frame counter according to the completion result specified by the ScheduledFrameCompleted callback. Consider an extra increment of two.
At least on Windows and for many years now, only workstation boards provide unthrottled pixel readback when using NVidia's products. My iMac has a GeForce series card but I haven't measured its performance. I wouldn't be surprised if glReadPixels is throttled.
Also try using GL_BGRA_EXT and GL_UNSIGNED_INT_8_8_8_8_REV.
You should have precision timing metrics for glReadPixels and the writes to hardware. I assume you're reading back progressive or interlaced frames but not fields. Ideally, pixel readback should be less than 10 ms. And obviously, the entire render cycle needs be faster than the video hardware's frame rate.

How do I populate a list of BLE iPads and iPhones using core bluetooth

I'm trying to create a simple browser using core bluetooth that discovers iPhones and iPads in the vicinity and displays them in a table view. Thus far, i'm implementing central Manager and receiving a notification. The information seems a little cryptic
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
NSLog(#"Did discover peripheral. peripheral: %# rssi: %#, UUID: %# advertisementData: %# ", peripheral, RSSI, peripheral.UUID, advertisementData);
}
The information seems a little cryptic, for and for some reason not all of the devices have a "name" parameter.
2014-09-22 13:11:13.142 WhoDat[3333:60b] Did discover peripheral. peripheral:
0x1780b4f40 identifier = 9373F3AD-726D-2EC9-AB2C-BBAB9B2ED319, Name = "(null)", state = disconnected> rssi: -63, UUID: <CFUUID 0x178036ee0> 9373F3AD-726D-2EC9-AB2C-BBAB9B2ED319 advertisementData: {
kCBAdvDataChannel = 37;
kCBAdvDataIsConnectable = 1;
}
while others do
2014-09-22 13:13:26.224 WhoDat[3333:60b] Did discover peripheral. peripheral: <CBPeripheral: 0x1700b4b80 identifier = 74E42396-CB35-3FB7-A855-F2BB78AC2C78, Name = "Zip", state = disconnected> rssi: -95, UUID: <CFUUID 0x17002da60> 74E42396-CB35-3FB7-A855-F2BB78AC2C78 advertisementData: {
kCBAdvDataChannel = 39;
kCBAdvDataIsConnectable = 1;
kCBAdvDataServiceData = {
"Device Information" = <0204>;
};
kCBAdvDataServiceUUIDs = (
"ADAB67D3-6E7D-4601-BDA2-BFFAA68956BA"
);
}
but I seem to have no way of differentiating what is what. Am I missing something?
The most likely reason you are not receiving a name is that the device is not advertising one inside of it's advertising package.
To make matters stranger, CoreBluetooth does some caching which will create strange inconsistencies when interacting with a device.
A chief example being a device that does not advertise it's name will show it's cached name if you connect to said device.
My suggestion would be to represent it with a string of "No Name" until you receive one via connecting to said device.

AudioQueue fails to start

I create an AudioQueue in the following steps.
Create a new output with AudioQueueNewOutput
Add a property listener for the kAudioQueueProperty_IsRunning property
Allocate my buffers with AudioQueueAllocateBuffer
Call AudioQueuePrime
Call AudioQueueStart
The problem is, when i call AudioQueuePrime it outputs following error on the console
AudioConverterNew returned -50
Prime failed (-50); will stop (11025/0 frames)
What's wrong here?
PS:
I got this error on iOS (Device & Simulator)
The output callback installed when calling AudioQueueNewOutput is never called!
The file is valid and the AudioStreamBasicDescription does match the format (AAC)
I tested the file with Mat's AudioStreamer and it seems to work there
Sample Init Code:
// Get the stream description from the first sample buffer
OSStatus err = noErr;
EDSampleBuffer *firstBuf = [sampleBufs objectAtIndex:0];
AudioStreamBasicDescription asbd = firstBuf.streamDescription;
// TODO: remove temporary format setup, just to ensure format for now
asbd.mSampleRate = 44100.00;
asbd.mFramesPerPacket = 1024; // AAC default
asbd.mChannelsPerFrame = 2;
pfcc(asbd.mFormatID);
// -----------------------------------
// Create a new output
err = AudioQueueNewOutput(&asbd, _audioQueueOutputCallback, self, NULL, NULL, 0, &audioQueue);
if (err) {
[self _reportError:kASAudioQueueInitializationError];
goto bail;
}
// Add property listener for queue state
err = AudioQueueAddPropertyListener(audioQueue, kAudioQueueProperty_IsRunning, _audioQueueIsRunningCallback, self);
if (err) {
[self _reportError:kASAudioQueuePropertyListenerError];
goto bail;
}
// Allocate a queue buffers
for (int i=0; i<kAQNumBufs; i++) {
err = AudioQueueAllocateBuffer(audioQueue, kAQDefaultBufSize, &queueBuffer[i]);
if (err) {
[self _reportError:kASAudioQueueBufferAllocationError];
goto bail;
}
}
// Prime and start
err = AudioQueuePrime(audioQueue, 0, NULL);
if (err) {
printf("failed to prime audio queue %ld\n", err);
goto bail;
}
err = AudioQueueStart(audioQueue, NULL);
if (err) {
printf("failed to start audio queue %ld\n", err);
goto bail;
}
These are the format flags from the audio file stream
rate: 44100.000000
framesPerPacket: 1024
format: aac
bitsPerChannel: 0
reserved: 0
channelsPerFrame: 2
bytesPerFrame: 0
bytesPerPacket: 0
formatFlags: 0
cookieSize 39
AudioConverterNew returned -50
Prime failed (-50); will stop (11025/0 frames)
What's wrong here?
You did it wrong.
No, really. That's what that error means, and that's ALL that error means.
That's why paramErr (-50) is such an annoying error code: It doesn't say a damn thing about what you (or anyone else) did wrong.
The first step to formulating guesses as to what it's complaining about is to find out what function returned that error. Change your _reportError: method to enable you to log the name of the function that returned the error. Then, log the parameters you're passing to that function and figure out why it's of the opinion that those parameters to that function don't make sense.
My own wild guess is that it's because the values you forced into the ASBD don't match the characteristics of the sample buffer. The log output you included in your question says “11025/0 frames”; 11025 is a common sample rate (but different from 44100). I assume you'd know what the 0 refers to.