I met a weird question.I have been using FFmpeg's NVENC to encode video .It is strange that I can use h264_nvenc smoothly without problem,but when I replace h264_nvenc with hevc_nvenc,I got the problem "No NVENC capable devices found".The FFmpeg version I am using is 3.2,and I use command line to encode with hevc_nvenc,it works ok.My code is here:
#include "stdafx.h"
int flush_encoder(AVFormatContext *fmt_ctx, unsigned int stream_index)
{
int ret;
int got_frame;
AVPacket enc_pkt;
if (!(fmt_ctx->streams[stream_index]->codec->codec->capabilities &
CODEC_CAP_DELAY))
return 0;
while (1) {
printf("Flushing stream #%u encoder\n", stream_index);
//ret = encode_write_frame(NULL, stream_index, &got_frame);
enc_pkt.data = NULL;
enc_pkt.size = 0;
av_init_packet(&enc_pkt);
ret = avcodec_encode_video2(fmt_ctx->streams[stream_index]->codec, &enc_pkt,
NULL, &got_frame);
av_frame_free(NULL);
if (ret < 0)
break;
if (!got_frame){
ret = 0;
break;
}
printf("Succeed to encode 1 frame! 编码成功1帧!\n");
/* mux encoded frame */
ret = av_write_frame(fmt_ctx, &enc_pkt);
if (ret < 0)
break;
}
return ret;
}
int main(int argc, char* argv[])
{
AVFormatContext* pFormatCtx;
AVOutputFormat* fmt;
AVStream* video_st;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
uint8_t* picture_buf;
AVFrame* picture;
int size;
FILE *in_file = fopen("test_yuv420p_320x180.yuv", "rb"); //Input YUV data 视频YUV源文件
int in_w = 320, in_h = 180;//宽高
int framenum = 100;
const char* out_file = "ds.hevc";
av_register_all();
//Method1 方法1.组合使用几个函数
pFormatCtx = avformat_alloc_context();
//Guess Format 猜格式
fmt = av_guess_format(NULL, out_file, NULL);
pFormatCtx->oformat = fmt;
//Method 2 方法2.更加自动化一些
//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
//fmt = pFormatCtx->oformat;
//Output Format 注意输出路径
if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0)
{
printf("Failed to open output file! 输出文件打开失败");
return -1;
}
video_st = avformat_new_stream(pFormatCtx, 0);
video_st->time_base.num = 1;
video_st->time_base.den = 25;
if (video_st == NULL)
{
return -1;
}
//Param that must set
pCodecCtx = video_st->codec;
pCodecCtx->codec_id =AV_CODEC_ID_HEVC;
//pCodecCtx->codec_id = fmt->video_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx->width = in_w;
pCodecCtx->height = in_h;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = 25;
pCodecCtx->bit_rate = 400000;
pCodecCtx->gop_size = 12;
//H264
//pCodecCtx->me_range = 16;
//pCodecCtx->max_qdiff = 4;
//pCodecCtx->qcompress = 0.6;
pCodecCtx->qmin = 10;
pCodecCtx->qmax = 51;
//Optional Param
pCodecCtx->max_b_frames = 3;
// Set Option
AVDictionary *param = 0;
//H.264
if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {
av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
}
//H.265
if (pCodecCtx->codec_id == AV_CODEC_ID_H265){
av_dict_set(¶m, "x265-params", "qp=20", 0);
av_dict_set(¶m, "preset", "default", 0);
av_dict_set(¶m, "tune", "zero-latency", 0);
}
//Dump Information 输出格式信息
av_dump_format(pFormatCtx, 0, out_file, 1);
//pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
pCodec = avcodec_find_encoder_by_name("hevc_nvenc");
if (!pCodec){
printf("Can not find encoder! 没有找到合适的编码器!\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0){
printf("Failed to open encoder! 编码器打开失败!\n");
return -1;
}
picture = av_frame_alloc();
size = avpicture_get_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
picture_buf = (uint8_t *)av_malloc(size);
avpicture_fill((AVPicture *)picture, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
//Write File Header 写文件头
avformat_write_header(pFormatCtx, NULL);
AVPacket pkt;
int y_size = pCodecCtx->width * pCodecCtx->height;
av_new_packet(&pkt, y_size * 3);
for (int i = 0; i<framenum; i++){
//Read YUV 读入YUV
if (fread(picture_buf, 1, y_size * 3 / 2, in_file) < 0){
printf("Failed to read YUV data! 文件读取错误\n");
return -1;
}
else if (feof(in_file)){
break;
}
picture->data[0] = picture_buf; // 亮度Y
picture->data[1] = picture_buf + y_size; // U
picture->data[2] = picture_buf + y_size * 5 / 4; // V
//PTS
picture->pts = i;
picture->format = pCodecCtx->pix_fmt;
picture->width = in_w;
picture->height = in_h;
int got_picture = 0;
//Encode 编码
int ret = avcodec_encode_video2(pCodecCtx, &pkt, picture, &got_picture);
if (ret < 0){
printf("Failed to encode! 编码错误!\n");
return -1;
}
if (got_picture == 1){
printf("Succeed to encode 1 frame! 编码成功1帧!\n");
pkt.stream_index = video_st->index;
ret = av_write_frame(pFormatCtx, &pkt);
av_free_packet(&pkt);
}
}
//Flush Encoder
int ret = flush_encoder(pFormatCtx, 0);
if (ret < 0) {
printf("Flushing encoder failed\n");
return -1;
}
//Write file trailer 写文件尾
av_write_trailer(pFormatCtx);
//Clean 清理
if (video_st){
avcodec_close(video_st->codec);
av_free(picture);
av_free(picture_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(in_file);
system("pause");
return 0;
}
Help!!!!
after a few days of strugglling,once again I try anwser the question myself.The key point is ,when encoding with hevc_nvenc,you must set pCodecCtx->max_b_frames = 0;(at least for version 3.2 of ffmpeg).
Related
So i have to create two set of coordinates depending on whether the latitude or longitude are even or odd. But this two errors wont let me read and save them correctly, and i have 0 clue on what to do.
This is the part of the code where i create that function.
So where it says numeros[j++]=datos[i++] is where the error is.
The locations are in a file saved like this:
37.3124631552;93.0636996608
20.4690509824;64.2966293504
25.230157824;13.5498533888
int CrearConjuntos (char NombreFichero[], char datos[MaxDatos][MaxCaracter], tConjunto *conjuntoUno, tConjunto *conjuntoDos)
{
int nComas=0, nComass=0;
char numeros[1000];
int aux,aux2;
int i, longitud[MaxDatos], num, a = 0, b = 0, c = 0,j;
FILE *pFich = fopen (NombreFichero, "r");
printf ("\n LEER FICHERO");
if (pFich == NULL)
{
printf ("\n\n Error: No se puede abrir el fichero \"%s\" ", NombreFichero);
}
else
{ for (i=0; i<MaxDatos; i++)
{
fgets (datos[i], MaxCaracter, pFich);
while(nComas<1){
if(datos[i]==';') nComas++;
numeros[j++] = datos[i++];
if(datos[i]=='.'){
numeros[j]= '\0';
aux=atoi(numeros);
}
}
if (aux%2==0)
{
num = i;
if (a == 0)
{
initCjto (conjuntoUno, num);
}
else
{
introducir (conjuntoUno, num);
}
a++;
}
}
for (i=0; i<MaxDatos; i++){
fgets (datos[i], MaxCaracter, pFich);
while(nComass<1){
if(datos[i]==';') nComass++;
i++;
}
i++, j=0;
while(datos[i]!='\0'){
numeros[j++] = datos[i++];
if(datos[i]=='.'){
numeros[j]= '\0';
aux2=atoi(numeros);
}
}
if (aux%2==1)
{
num = i;
if (b == 0)
{
initCjto (conjuntoDos, num);
}
else
{
introducir (conjuntoDos, num);
}
b++;
}
}
fclose(pFich);
return 1;
}
}
While decoding H264 video via Windows Media Foundation using IMFSourceReader, I am seeing an unexpected y-offset in the U/V plane data. By trial and error, I have found an adjustment that seems to work on all the video sources I've tried, but I'd really like to know if this data layout is expected or documented.
Specifically, sometimes IMFSample::GetTotalLength() returns a total buffer size that is greater than height * stride * 3/2. In that case, the U/V planes are offset from the end of the Y plane data by 2/3 of the extra data, like so:
https://stash.reaper.fm/44192/YV12.png
To be clear, the unexpected part is the N rows of pixels below the Y plane data and above the U plane data. I think all of the other offsets and padding are as expected. Is this data layout expected or documented?
Image before applying adjustment:
https://stash.reaper.fm/44193/before.jpg
Image after applying adjustment:
https://stash.reaper.fm/44194/after.jpg
The video:
https://stash.reaper.fm/44214/johnny.mp4
Here is a complete program that draws the first frame of the video with and without the adjustment. There is no error checking and the YUV to RGB conversion is very basic.
#include <windows.h>
#include <initguid.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include "resource.h"
const int marg=16;
unsigned char clamp(int v)
{
return v < 0 ? 0 : v > 255 ? 255 : v;
}
void yuv_to_rgb(unsigned char *rgb, int y, int u, int v)
{
y -= 16;
u -= 128;
v -= 128;
rgb[3] = 0;
rgb[2] = clamp((y*298 + v*409 + 128) / 256);
rgb[1] = clamp((y*298 - u*100 - v*208 + 128) / 256);
rgb[0] = clamp((y*298 + u*516 + 128) / 256);
}
INT_PTR CALLBACK wndproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HBITMAP rawbmp = NULL, adjbmp=NULL;
static unsigned int srcw = 0, srch = 0;
switch (uMsg)
{
case WM_INITDIALOG:
{
MFStartup(MF_VERSION);
IMFSourceReader *reader = NULL;
MFCreateSourceReaderFromURL(L"C:\\Users\\xxx\\Documents\\johnny.mp4", NULL, &reader);
reader->SetStreamSelection(MF_SOURCE_READER_ALL_STREAMS, FALSE);
reader->SetStreamSelection(MF_SOURCE_READER_FIRST_VIDEO_STREAM, TRUE);
IMFMediaType *fmt = NULL;
MFCreateMediaType(&fmt);
fmt->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video);
fmt->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_YV12);
reader->SetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, fmt);
fmt->Release();
reader->GetCurrentMediaType(MF_SOURCE_READER_FIRST_VIDEO_STREAM, &fmt);
MFGetAttributeSize(fmt, MF_MT_FRAME_SIZE, &srcw, &srch);
fmt->Release();
IMFSample *sample = NULL;
DWORD flags=0;
INT64 readpos=0;
IMFMediaBuffer *buffer = NULL;
DWORD bufsz=0;
reader->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, &flags, &readpos, &sample);
sample->GetTotalLength(&bufsz);
sample->ConvertToContiguousBuffer(&buffer);
sample->Release();
reader->Release();
BITMAPINFO bi = {0};
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi.bmiHeader.biWidth = srcw;
bi.bmiHeader.biHeight = srch;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 32;
bi.bmiHeader.biCompression = BI_RGB;
unsigned char *raw = NULL, *adj=NULL;
rawbmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&raw, NULL, 0);
adjbmp = CreateDIBSection(NULL, &bi, DIB_RGB_COLORS, (void**)&adj, NULL, 0);
IMF2DBuffer *buffer2d = NULL;
BYTE *bptr = NULL;
LONG bstride = 0;
buffer->QueryInterface(&buffer2d);
buffer2d->Lock2D(&bptr, &bstride);
int offs=(bufsz*2/3-srch*bstride); // unexpected
unsigned char *rawptr = raw + srcw*(srch-1)*4;
unsigned char *adjptr = adj + srcw*(srch-1)*4;
unsigned char *yptr = bptr;
unsigned char *uptr = bptr + srch*bstride*5/4;
unsigned char *vptr = bptr + srch*bstride;
for (unsigned int y=0; y < srch; ++y)
{
for (unsigned int x=0; x < srcw; ++x)
{
yuv_to_rgb(rawptr+x*4, yptr[x], uptr[x/2], vptr[x/2]);
yuv_to_rgb(adjptr+x*4, yptr[x], uptr[x/2+offs], vptr[x/2+offs]);
}
rawptr -= srcw*4;
adjptr -= srcw*4;
yptr += bstride;
if (y&1) uptr += bstride/2;
if (y&1) vptr += bstride/2;
}
buffer2d->Unlock2D();
buffer2d->Release();
buffer->Release();
SetWindowPos(hwndDlg, NULL, 0, 0, srcw+2*marg, 2*(srch+2*marg), SWP_NOZORDER|SWP_NOMOVE|SWP_NOACTIVATE);
}
return 0;
case WM_DESTROY:
{
DeleteObject(rawbmp);
DeleteObject(adjbmp);
}
return 0;
case WM_PAINT:
{
RECT r;
GetClientRect(hwndDlg, &r);
int w=r.right, h=r.bottom;
PAINTSTRUCT ps;
HDC dc = BeginPaint(hwndDlg, &ps);
HDC srcdc = CreateCompatibleDC(dc);
SelectObject(srcdc, rawbmp);
BitBlt(dc, marg/2, marg/2, srcw, srch, srcdc, 0, 0, SRCCOPY);
SelectObject(srcdc, adjbmp);
BitBlt(dc, marg/2, (h+marg)/2, srcw, srch, srcdc, 0, 0, SRCCOPY);
EndPaint(hwndDlg, &ps);
ReleaseDC(hwndDlg, srcdc);
}
return 0;
case WM_COMMAND:
if (LOWORD(wParam) == IDCANCEL)
{
EndDialog(hwndDlg, 0);
}
return 0;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG), GetDesktopWindow(), wndproc);
return 0;
}
For a project I´m following this tutorial on how to track the location and output the GPS data using an Arduino with this SIM908 shield. The Arduino correctly sends the GPS data to the database. However, the coordinates are all exactly the same and it seems that they have been rounded off.
For example:
Latitude: 52.216667
Longitude: 5.483333
This isn't because of the PHP script, all it does is put the data it receives in the database. My guess is that it has something to do with the conversion function convert2Degrees.
This is the code we´re running on our Arduino:
int8_t answer;
int onModulePin= 2;
char data[100];
int data_size;
char aux_str[100];
char aux;
int x = 0;
char N_S,W_E;
char url[] = "informatica-corlaer.nl";
char frame[200];
char pin[]="0000";
char apn[]="mmm.nl";
char user_name[]="";
char password[]="";
char latitude[15];
char longitude[15];
char altitude[10];
char date[16];
char time[7];
char satellites[3];
char speedOTG[10];
char course[10];
void setup(){
pinMode(onModulePin, OUTPUT);
Serial.begin(115200);
Serial.println("Starting...");
power_on();
delay(3000);
//sets the PIN code
snprintf(aux_str, sizeof(aux_str), "AT+CPIN=%s", pin);
sendATcommand(aux_str, "OK", 2000);
delay(3000);
// starts the GPS and waits for signal
while ( start_GPS() == 0);
while (sendATcommand("AT+CREG?", "+CREG: 0,1", 2000) == 0);
// sets APN , user name and password
sendATcommand("AT+SAPBR=3,1,\"Contype\",\"GPRS\"", "OK", 2000);
snprintf(aux_str, sizeof(aux_str), "AT+SAPBR=3,1,\"APN\",\"%s\"", apn);
sendATcommand(aux_str, "OK", 2000);
snprintf(aux_str, sizeof(aux_str), "AT+SAPBR=3,1,\"USER\",\"%s\"", user_name);
sendATcommand(aux_str, "OK", 2000);
snprintf(aux_str, sizeof(aux_str), "AT+SAPBR=3,1,\"PWD\",\"%s\"", password);
sendATcommand(aux_str, "OK", 2000);
// gets the GPRS bearer
while (sendATcommand("AT+SAPBR=1,1", "OK", 20000) == 0)
{
delay(5000);
}
}
void loop(){
// gets GPS data
get_GPS();
// sends GPS data to the script
send_HTTP();
delay(5000);
}
void power_on(){
uint8_t answer=0;
// checks if the module is started
answer = sendATcommand("AT", "OK", 2000);
if (answer == 0)
{
// power on pulse
digitalWrite(onModulePin,HIGH);
delay(3000);
digitalWrite(onModulePin,LOW);
// waits for an answer from the module
while(answer == 0){
// Send AT every two seconds and wait for the answer
answer = sendATcommand("AT", "OK", 2000);
}
}
}
int8_t start_GPS(){
unsigned long previous;
previous = millis();
// starts the GPS
sendATcommand("AT+CGPSPWR=1", "OK", 2000);
sendATcommand("AT+CGPSRST=0", "OK", 2000);
// waits for fix GPS
while(( (sendATcommand("AT+CGPSSTATUS?", "2D Fix", 5000) ||
sendATcommand("AT+CGPSSTATUS?", "3D Fix", 5000)) == 0 ) &&
((millis() - previous) < 90000));
if ((millis() - previous) < 90000)
{
return 1;
}
else
{
return 0;
}
}
int8_t get_GPS(){
int8_t counter, answer;
long previous;
// First get the NMEA string
// Clean the input buffer
while( Serial.available() > 0) Serial.read();
// request Basic string
sendATcommand("AT+CGPSINF=0", "AT+CGPSINF=0\r\n\r\n", 2000);
counter = 0;
answer = 0;
memset(frame, '\0', 100); // Initialize the string
previous = millis();
// this loop waits for the NMEA string
do{
if(Serial.available() != 0){
frame[counter] = Serial.read();
counter++;
// check if the desired answer is in the response of the module
if (strstr(frame, "OK") != NULL)
{
answer = 1;
}
}
// Waits for the asnwer with time out
}
while((answer == 0) && ((millis() - previous) < 2000));
frame[counter-3] = '\0';
// Parses the string
strtok(frame, ",");
strcpy(longitude,strtok(NULL, ",")); // Gets longitude
strcpy(latitude,strtok(NULL, ",")); // Gets latitude
strcpy(altitude,strtok(NULL, ".")); // Gets altitude
strtok(NULL, ",");
strcpy(date,strtok(NULL, ".")); // Gets date
strtok(NULL, ",");
strtok(NULL, ",");
strcpy(satellites,strtok(NULL, ",")); // Gets satellites
strcpy(speedOTG,strtok(NULL, ",")); // Gets speed over ground. Unit is knots.
strcpy(course,strtok(NULL, "\r")); // Gets course
convert2Degrees(latitude);
convert2Degrees(longitude);
return answer;
}
/* convert2Degrees ( input ) - performs the conversion from input
* parameters in DD°MM.mmm’ notation to DD.dddddd° notation.
*
* Sign '+' is set for positive latitudes/longitudes (North, East)
* Sign '-' is set for negative latitudes/longitudes (South, West)
*
*/
int8_t convert2Degrees(char* input){
float deg;
float minutes;
boolean neg = false;
//auxiliar variable
char aux[10];
if (input[0] == '-')
{
neg = true;
strcpy(aux, strtok(input+1, "."));
}
else
{
strcpy(aux, strtok(input, "."));
}
// convert string to integer and add it to final float variable
deg = atof(aux);
strcpy(aux, strtok(NULL, '\0'));
minutes=atof(aux);
minutes/=1000000;
if (deg < 100)
{
minutes += deg;
deg = 0;
}
else
{
minutes += int(deg) % 100;
deg = int(deg) / 100;
}
// add minutes to degrees
deg=deg+minutes/60;
if (neg == true)
{
deg*=-1.0;
}
neg = false;
if( deg < 0 ){
neg = true;
deg*=-1;
}
float numberFloat=deg;
int intPart[10];
int digit;
long newNumber=(long)numberFloat;
int size=0;
while(1){
size=size+1;
digit=newNumber%10;
newNumber=newNumber/10;
intPart[size-1]=digit;
if (newNumber==0){
break;
}
}
int index=0;
if( neg ){
index++;
input[0]='-';
}
for (int i=size-1; i >= 0; i--)
{
input[index]=intPart[i]+'0';
index++;
}
input[index]='.';
index++;
numberFloat=(numberFloat-(int)numberFloat);
for (int i=1; i<=10 ; i++)
{
numberFloat=numberFloat*10;
digit= (long)numberFloat;
numberFloat=numberFloat-digit;
input[index]=char(digit)+48;
index++;
}
input[index]='\0';
}
void send_HTTP(){
uint8_t answer=0;
// Initializes HTTP service
answer = sendATcommand("AT+HTTPINIT", "OK", 10000);
if (answer == 1)
{
// Sets CID parameter
answer = sendATcommand("AT+HTTPPARA=\"CID\",1", "OK", 5000);
if (answer == 1)
{
// Sets url
sprintf(aux_str, "AT+HTTPPARA=\"URL\",\"http://%s/vehicleLocationTransmitter.php?", url);
Serial.print(aux_str);
sprintf(frame, "vehicleID=1&latitude=%s&longitude=%s&altitude=%s&time=%s&satellites=%s",
latitude, longitude, altitude, date, satellites);
Serial.print(frame);
answer = sendATcommand("\"", "OK", 5000);
if (answer == 1)
{
// Starts GET action
answer = sendATcommand("AT+HTTPACTION=0", "+HTTPACTION:0,200", 30000);
if (answer == 1)
{
Serial.println(F("Done!"));
}
else
{
Serial.println(F("Error getting url"));
}
}
else
{
Serial.println(F("Error setting the url"));
}
}
else
{
Serial.println(F("Error setting the CID"));
}
}
else
{
Serial.println(F("Error initializating"));
}
sendATcommand("AT+HTTPTERM", "OK", 5000);
}
int8_t sendATcommand(char* ATcommand, char* expected_answer1, unsigned int timeout){
uint8_t x=0, answer=0;
char response[100];
unsigned long previous;
memset(response, '\0', 100); // Initialize the string
delay(100);
while( Serial.available() > 0) Serial.read(); // Clean the input buffer
Serial.println(ATcommand); // Send the AT command
x = 0;
previous = millis();
// this loop waits for the answer
do{
if(Serial.available() != 0){
response[x] = Serial.read();
x++;
// check if the desired answer is in the response of the module
if (strstr(response, expected_answer1) != NULL)
{
answer = 1;
}
}
// Waits for the asnwer with time out
}
while((answer == 0) && ((millis() - previous) < timeout));
return answer;
}
Write a test case for the function in doubt (convert2Degrees())
from the comment: "parameters in DD°MM.mmm’ notation to DD.dddddd°":
If you input: 52°27.123
Then the expected Output should be: 52.45205
Calculation: 52°27.123 = 52 + 27.123/60.0 =
= 52.45205
Further you should post here the value which is input to convert2Degrees()
Your use of strtok is incorrect, and the convert2degrees has major problems.
Here's something derived from NeoGPS that doesn't use the expensive (on AVRs) divide or modulo arithmetic:
//.................................................
// A special divide-by-3 function that avoids division.
// From http://www.hackersdelight.org/divcMore.pdf
static uint32_t divu3( uint32_t n )
{
uint32_t q = (n >> 2) + (n >> 4); // q = n*0.0101 (approx).
q = q + (q >> 4); // q = n*0.01010101.
q = q + (q >> 8);
q = q + (q >> 16);
uint32_t r = n - q*3; // 0 <= r <= 15.
return q + (11*r >> 5); // Returning q + r/3.
}
//------------------------------------------------------------
// Parse the NMEA "DDDMM.mmmm" format for lat and lon.
//
// returns degrees * 10^7
uint32_t parseDDMMmmmm( char *input )
{
uint8_t digits = 0;
uint8_t sixth_digit = 0;
char chr;
// Find the decimal point
while (isdigit( input[digits] ))
digits++;
// All but the last two are degrees.
uint32_t val = 0;
while (digits > 2) {
chr = *input++;
val = val*10 + (chr - '0');
digits--;
}
// convert from degrees to minutes
val *= 60;
// Add in the last 2 minutes digits
uint8_t minutes = 0;
while (digits > 0) {
chr = *input++;
minutes = minutes*10 + (chr - '0');
digits--;
}
val += minutes;
// Decimal point?
chr = *input++;
if (chr == '.') {
chr = *input++;
// Parse up to 6 digits of the fractional minutes.
while ((digits++ < 5) && isdigit( chr )) {
val = val*10 + (chr - '0');
chr = *input++;
}
if ((digits == 6) && isdigit(chr)) {
sixth_digit = chr - '0';
digits++;
}
// Scale the value up to minutes x 1000000.
while (digits < 4) {
val *= 10;
digits++;
}
}
// convert from minutes x 1000000 to degrees x 10000000.
val += divu3( val*2 + 1 ); // same as 10 * (val+30)/60 without truncation
if (digits >= 6) {
if (sixth_digit >= 9)
val += 2;
else if (sixth_digit >= 4)
val += 1;
}
return val;
} // parseDDMMmmmm
...and a floating-point version:
double parseDDMMmmmm_f( char *input )
{
uint8_t digits = 0;
char chr;
// Find the decimal point
while (isdigit( input[digits] ))
digits++;
// All but the last two are degrees.
double val = 0.0;
while (digits > 2) {
chr = *input++;
val = val*10 + (chr - '0');
digits--;
}
// convert from degrees to minutes
val *= 60;
// Add in the last 2 minutes digits
uint8_t minutes = 0;
while (digits > 0) {
chr = *input++;
minutes = minutes*10 + (chr - '0');
digits--;
}
val += minutes;
// Decimal point?
chr = *input++;
if (chr == '.') {
chr = *input++;
// Parse the fractional "mmmm" minutes.
while (isdigit( chr ) && (digits++ <= 4)) {
val = val*10 + (chr - '0');
chr = *input++;
}
// Scale the value up to minutes x 1000000.
while (digits < 4) {
val *= 10;
digits++;
}
}
// convert from minutes x 1000000 to degrees.
val *= 10.0/1000000.0 * 1.0/60.0;
return val;
} // parseDDMMmmmm_f
If you use these functions, you also need to pop the '-' off the front of your AT string, and negate the returned values:
bool south = (latitude[0] == '-');
if (south)
latitude++;
float lat = parseDDMMmmmm_f( latitude );
if (south)
lat = -lat;
convert2Degrees(longitude);
bool west = (longitude[0] == '-');
if (west)
longitude++;
float lon = parseDDMMmmmm_f( longitude );
if (west)
lon = -lon;[/code]
I'm trying to put items from a csv file in an hashmap. By adding items I mean categorizing them. The csv is filled with the answers from a question list. So the csv is build up like this:
Person Question
- Do you wear glasses
1 Yes
2 Yes
3 No
4 Sometimes
The next step I would like to do is reading the items and put the answer in the hashmap with the key being the name of the answer and the value with the amount of that certain answer.
The hashmap should look like this with the previous example I gave:
Yes, 2
No, 1
Sometimes, 1
I'm looping right now like this:
for (int j = 0; j < dataPersonList.size(); j++)
{
// looping through the csv
while (t.hasNext ())
{
// looping through the hashmap
Map.Entry me = (Map.Entry)t.next();
if (dataPersonVar.glasses.equals(me.getKey()))
{
// if the item in the csv is the same as the item in the hashmap
hm.put(me.getKey(), me.getValue() =+ 1); // the value gets +1
}
else
{
// a new item is made and gets automatically 1
hm.put(dataPersonVar.glasses,1);
}
}
}
But obviously this doesn't work. I'm a starter with hashmaps but really think the hashmap is the solution for my problem. I'm working in Processing. Does anybody have an idea how to solve this? If I'm not clear enough let me know!
Thanks in advance
Edit:
As requested I hereby post the full code:
import java.util.Iterator;
import java.util.Map;
HashMap hm = new HashMap();
import de.bezier.data.*;
int totalParticipants;
int bgWidth = 1000;
int bgHeight = 1000;
int x;
int eSize = 10;
int opacity = 100;
float xLocation;
float yLocation;
String travelType;
int travelTime;
int border=400;
float dataMinLat=1000;
float dataMaxLat;
float dataMinLon=1000;
float dataMaxLon;
float xLocationMM = (5.17880);
float yLocationMM = (52.22541);
ArrayList dataPersonList = new ArrayList();
ArrayList dataFunctionList = new ArrayList(100);
Point[] pointList = new Point[1000];
float angle;
XlsReader reader;
PImage kaart;
void setup ()
{
textSize(10);
size(bgWidth, bgHeight);
background(0);
noStroke();
smooth();
//kaart = loadImage("map.png");
yLocationMM = 0 - yLocationMM;
reader = new XlsReader( this, "MMdata.xls" ); // assumes file to be in the data folder
totalParticipants = reader.getLastRowNum();
for (int i = 1;i < totalParticipants+1; i++) {
DataPerson dataPerson = new DataPerson();
dataPerson.function = reader.getString(i, 23);
dataPerson.firstName = reader.getString(i, 1);
dataPerson.lastName = reader.getString(i, 2);
dataPerson.glasses = reader.getString(i, 20);
dataPerson.longitude = reader.getFloat(i, 55);
dataPerson.latitude = reader.getFloat(i, 54);
dataPerson.location = reader.getString(i, 8);
dataPerson.ownage = reader.getString(i, 14);
dataPerson.traveltime = reader.getInt(i, 31);
dataPerson.establishment = reader.getString(i, 58);
dataPerson.traveltype = reader.getString(i, 17);
dataPersonList.add(dataPerson);
}
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson person = (DataPerson) dataPersonList.get(i);
for (int j = 0; j < dataFunctionList.size() + 1; j++) {
DataFunction dataFunction = null;
if (j < dataFunctionList.size())
{
dataFunction = (DataFunction) dataFunctionList.get(j);
}
if (dataFunction != null) {
if (person.function.equals(dataFunction.function)) {
dataFunction.persons.add(person);
dataFunction.amount ++;
break;
}
}
else {
dataFunction = new DataFunction();
dataFunction.function = person.function;
dataFunction.amount = 1;
dataFunction.persons.add(person);
dataFunctionList.add(dataFunction);
break;
}
}
}
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson dataPersonVar = (DataPerson) dataPersonList.get(i);
if (dataPersonVar.longitude > dataMaxLon) {
dataMaxLon = dataPersonVar.longitude;
}
else if (dataPersonVar.longitude < dataMinLon) {
dataMinLon = dataPersonVar.longitude;
}
if (dataPersonVar.latitude > dataMaxLat) {
dataMaxLat = dataPersonVar.latitude;
}
else if (dataPersonVar.latitude < dataMinLat) {
dataMinLat = dataPersonVar.latitude;
}
}
}
class DataPerson
{
String function;
String firstName;
String lastName;
String glasses;
float longitude;
float latitude;
String location;
String ownage;
int traveltime;
String establishment;
String traveltype;
String fullName()
{
return firstName + " " + lastName;
}
}
class DataFunction
{
String function;
int amount;
ArrayList persons = new ArrayList();
String getPersonNames()
{
String output = "";
for (int i = 0; i < persons.size(); i++) {
DataPerson person = (DataPerson) persons.get(i);
output += person.firstName + "(" + person.glasses + ") ";
}
return output;
}
}
class Point
{
float x;
float y;
}
void draw()
{
background(0);
strokeWeight(2);
x=50;
int xText=80;
int procentGlasses;
noStroke();
pushMatrix();
scale(1.40, 0.89);
//image(kaart, -250, -360);
popMatrix();
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson dataPersonVar = (DataPerson) dataPersonList.get(i);
if (dataPersonVar != null) {
xLocation = map(dataPersonVar.longitude, dataMinLon, dataMaxLon, border, bgWidth-border);
yLocation = map(dataPersonVar.latitude, dataMinLat, dataMinLat+(dataMaxLon-dataMinLon), border, bgHeight-border);
travelType = (dataPersonVar.traveltype);
noFill();
if (travelType.equals("By car")) {
stroke(0, 0, 255, opacity+100);
}
else if (travelType.equals("By public transport")) {
stroke(255, 0, 0, opacity);
}
else {
stroke(255, opacity);
}
//text(dataPersonVar.firstName, xLocation, yLocation);
noStroke();
strokeWeight(4);
stroke(100, 15);
strokeWeight(2);
}
}
for (int i = 0; i < dataPersonList.size(); i++) {
DataPerson dataPersonVar = (DataPerson) dataPersonList.get(i);
if (dataPersonVar != null) {
xLocation = map(dataPersonVar.longitude, dataMinLon, dataMaxLon, border, bgWidth-200);
yLocation = map(dataPersonVar.latitude, dataMinLat, dataMinLat+(dataMaxLon-dataMinLon), border, bgHeight-200);
noStroke();
fill(255, 200);
ellipse(xLocation, yLocation, eSize, eSize);
//println(dataPersonVar.glasses);
Iterator t = hm.entrySet().iterator(); // Get an iterator
for (int j = 0; j < dataPersonList.size(); j++) {
while (t.hasNext ()) {
Map.Entry me = (Map.Entry)t.next();
println("die in de dataPersonshit is "+dataPersonVar.glasses+". En de andere waarde is "+me.getKey());
if (dataPersonVar.glasses.equals(me.getKey())) {
hm.put(me.getKey(), ((Integer)me.getValue()) + 1);
}
else {
hm.put(dataPersonVar.glasses, 1);
//println("YEAH");
}
}
}
/////////drawing the circle///////////////
angle = ((PI*2)/15*1)/dataPersonList.size()*i;
stroke(255, 100, 50, 50);
noFill();
strokeWeight(3);
pointList[i] = new Point();
pointList[i].x = bgWidth/2+sin(angle)*400; // de punt van x = 400 ( het middelpunt van de cirkel ) + sin((360 graden) / het totaal
pointList[i].y = bgHeight/2+cos(angle)*400;
beginShape();
vertex(xLocation, yLocation);
quadraticVertex((xLocation+pointList[i].x)/2, yLocation, pointList[i].x, pointList[i].y);
endShape();
}
}
}
Unfortunately I can't give you the csv but I hope the code at least helps.
You don't really need to iterate over the map to do what you seem to be trying to do. Here is an example with a similar csv as you have described:
import java.util.Map;
Map<String, Integer> answers = new HashMap<String,Integer>();
//String [] fileInput = loadStrings("question.csv");
String [] fileInput = new String [] {
"1,Yes", "2,No", "3,Yes", "4,Sometimes", "5,Yes", "6,No", "7,No", "8,No"
};
for (int i = 0 ; i < fileInput.length; i++) {
String [] line = split(fileInput[i],",");
String newAnswer = line[1];
if(!answers.containsKey(newAnswer)) answers.put(newAnswer,1);
else answers.put(newAnswer,answers.get(newAnswer)+1);
}
println(answers);
I'm interested in unescaping text for example: \ maps to \ in C. Does anyone know of a good library?
As reference the Wikipedia List of XML and HTML Character Entity References.
For another open source reference in C to decoding these HTML entities you can check out the command line utility uni2ascii/ascii2uni. The relevant files are enttbl.{c,h} for entity lookup and putu8.c which down converts from UTF32 to UTF8.
uni2ascii
I wrote my own unescape code; very simplified, but does the job: pn_util.c
Function Description: Convert special HTML entities back to characters.
Need to do some modifications to fit your requirement.
char* HtmlSpecialChars_Decode(char* encodedHtmlSpecialEntities)
{
int encodedLen = 0;
int escapeArrayLen = 0;
static char decodedHtmlSpecialChars[TITLE_SIZE];
char innerHtmlSpecialEntities[MAX_CONFIG_ITEM_SIZE];
/* This mapping table can be extended if necessary. */
static const struct {
const char* encodedEntity;
const char decodedChar;
} entityToChars[] = {
{"<", '<'},
{">", '>'},
{"&", '&'},
{""", '"'},
{"'", '\''},
};
if(strchr(encodedHtmlSpecialEntities, '&') == NULL)
return encodedHtmlSpecialEntities;
memset(decodedHtmlSpecialChars, '\0', TITLE_SIZE);
memset(innerHtmlSpecialEntities, '\0', MAX_CONFIG_ITEM_SIZE);
escapeArrayLen = sizeof(entityToChars) / sizeof(entityToChars[0]);
strcpy(innerHtmlSpecialEntities, encodedHtmlSpecialEntities);
encodedLen = strlen(innerHtmlSpecialEntities);
for(int i = 0; i < encodedLen; i++)
{
if(innerHtmlSpecialEntities[i] == '&')
{
/* Potential encode char. */
char * tempEntities = innerHtmlSpecialEntities + i;
for(int j = 0; j < escapeArrayLen; j++)
{
if(strncmp(tempEntities, entityToChars[j].encodedEntity, strlen(entityToChars[j].encodedEntity)) == 0)
{
int index = 0;
strncat(decodedHtmlSpecialChars, innerHtmlSpecialEntities, i);
index = strlen(decodedHtmlSpecialChars);
decodedHtmlSpecialChars[index] = entityToChars[j].decodedChar;
if(strlen(tempEntities) > strlen(entityToChars[j].encodedEntity))
{
/* Not to the end, continue */
char temp[MAX_CONFIG_ITEM_SIZE] = {'\0'};
strcpy(temp, tempEntities + strlen(entityToChars[j].encodedEntity));
memset(innerHtmlSpecialEntities, '\0', MAX_CONFIG_ITEM_SIZE);
strcpy(innerHtmlSpecialEntities, temp);
encodedLen = strlen(innerHtmlSpecialEntities);
i = -1;
}
else
encodedLen = 0;
break;
}
}
}
}
if(encodedLen != 0)
strcat(decodedHtmlSpecialChars, innerHtmlSpecialEntities);
return decodedHtmlSpecialChars;
}
QString UNESC(const QString &txt) {
QStringList bld;
static QChar AMP = '&', SCL = ';';
static QMap<QString, QString> dec = {
{"<", "<"}, {">", ">"}
, {"&", "&"}, {""", R"(")"}, {"'", "'"} };
if(!txt.contains(AMP)) { return txt; }
int bgn = 0, pos = 0;
while((pos = txt.indexOf(AMP, pos)) != -1) {
int end = txt.indexOf(SCL, pos)+1;
QString val = dec[txt.mid(pos, end - pos)];
bld << txt.mid(bgn, pos - bgn);
if(val.isEmpty()) {
end = txt.indexOf(AMP, pos+1);
bld << txt.mid(pos, end - pos);
} else {
bld << val;
}// else // if(val.isEmpty())
bgn = end; pos = end;
}// while((pos = txt.indexOf(AMP, pos)) != -1)
return bld.join(QString());
}// UNESC